2017-10-13 1 views
1

J'utilise Python 3.6 avec Django Framework.Diviser dynamiquement un dictionnaire en plusieurs dictionnaires dans python3.6 en fonction de l'entrée fournie

Je reçois l'entrée de l'utilisateur & cette entrée vient sous la forme de dictionnaire dans mon views.py. Disons que, l'utilisateur entre 3 valeurs que mon dictionnaire tiendra valeur comme

my_dict = {'name1': abc, 'job1': xyz, 'pos1':tak, 'phone1': 12345, 'name2': pqr, 'job2': ftr, 'pos2': lkj, 'phone2': 27654, 'name3': swq, 'job3': nme, 'pos3': mnb, 'phone3': 98421} 

Je cherche à créer des sous dictionnaires en fonction de l'entrée utilisateur, dans le cas ci-dessus 3. Sortie prévue est

dict1 = {'name1': abc, 'job1': xyz, 'pos1': tak, 'phone1': 12345} 
dict2 = {'name2': pqr, 'job2': ftr, 'pos2': lkj, 'phone2': 27654} 
dict3 = {'name3': swq, 'job3': nme, 'pos3': mnb, 'phone3': 98421} 

Maintenant, le problème ici est que nous ne savons pas quel est le nombre d'enregistrements que nous recevons de l'utilisateur, donc les sous-dictionnaires doivent également être créés dynamiquement. "dict1" à "dictn" où "n" est le numéro donné par l'utilisateur. Veuillez nous suggérer!

+3

Vous voulez _don't_ dictionnaires nommés séparés pour cela. Vous voulez une collection de dictionnaires, c'est-à-dire, vous devriez stocker ces sous-dictionnaires dans une liste ou peut-être un dictionnaire. –

+0

Ces clés seront-elles toujours dans ce format? Nous avons donc un des mots ('nom', 'travail', 'pos', 'téléphone') suivi d'un nombre. Est-ce exact? Est-ce que le nombre sera toujours un seul chiffre, ou devrez-vous gérer de plus gros nombres? –

+0

il suffit de calculer la longueur du dictionnaire, puis diviser puis diviser par le nombre de paramètres que chaque utilisateur peut avoir. –

Répondre

1

Ce code gère toutes les clés commençant par des lettres et se terminant par un nombre pouvant contenir un nombre quelconque de chiffres. Si une clé ne se termine pas par un nombre, elle imprime un message d'erreur, un programme approprié devrait mieux gérer les erreurs.

Il enregistre chaque dictionnaire résultant dans un dictionnaire sub_dicts, il n'a donc pas besoin de trier les données d'entrée.

import re 

# Make a regex that finds the number 
pat = re.compile(r'\d+') 

my_dict = { 
    'name1': 'abc', 'job1': 'xyz', 'pos1': 'tak', 'phone1': 12345, 
    'name2': 'pqr', 'job2': 'ftr', 'pos2': 'lkj', 'phone2': 27654, 
    'name3': 'swq', 'job3': 'nme', 'pos3': 'mnb', 'phone3': 98421, 
    'bad': 'bad_data', 
} 

# Separate the data based on the trailing number of each key. 
sub_dicts = {} 
for k, v in my_dict.items(): 
    m = pat.search(k) 
    if m: 
     num = m.group() 
     sub_dicts.setdefault(num, {})[k] = v 
    else: 
     print('Invalid key:', k, v) 

for k in sub_dicts.keys(): 
    print(sub_dicts[k]) 

sortie

Invalid key: bad bad_data 
{'name1': 'abc', 'job1': 'xyz', 'pos1': 'tak', 'phone1': 12345} 
{'name2': 'pqr', 'job2': 'ftr', 'pos2': 'lkj', 'phone2': 27654} 
{'name3': 'swq', 'job3': 'nme', 'pos3': 'mnb', 'phone3': 98421} 
+0

Merci, votre solution a fonctionné –

+0

Ring Y at-il un moyen d'obtenir la sortie dans 3 dictionnaires différents? Maintenant, nous les obtenons en tant que sous-répertoires. –

+0

@JeevanBodas Ils ont 3 dictionnaires différents. Mais vous pouvez y accéder via le dictionnaire 'sub_dicts' dans lequel ils" vivent ". Comme je l'ai dit au début, vous ne les voulez pas dans des variables totalement séparées. Comment allez-vous gérer cela quand vous ne savez pas jusqu'à l'exécution s'il y en aura 3 ou 99? Il est certainement possible de le faire, mais il n'y a pas de bonne raison de le faire, et n'importe quel expert en Python vous dira que c'est de la folie. ;) –

0

Je ne créerais pas de dictionnaires séparés, mais plutôt un dictionnaire de dictionnaires, ou, comme suggéré dans le commentaire, une liste d'entre eux. Voici la première approche:

new_dict = dict() 
for k, v in my_dict.iteritems(): 
    k_ = k[-1] 
    if not new_dict.get(k_): 
     new_dict[k_] = dict() 
    new_dict[k_][k] = v 

EDIT: Pour créer des dictionnaires séparés (que je ne recommande pas, cependant), vous pouvez le faire:

for k, v in new_dict.iteritems(): 
    globals()['dict' + k] = v 

Maintenant vous avez dict1, dict2 etc.

+0

@ PM2Ring Merci, corrigé. –

+0

Linhart Existe-t-il un moyen d'obtenir la sortie dans 3 dictionnaires différents? Maintenant, nous les obtenons comme sous-répertoires –

+0

@JeevanBodas Edited my answer. –

1

Vous pouvez effectuer les opérations suivantes en utilisant des expressions régulières pour fournir itertools.groupby avec une fonction de touche qui utilise une séquence de chiffres à la fin de chaque dict. clé:

from itertools import groupby 
import re 

key = lambda s: int(re.search(r'(\d+)$', s).group(1)) 
d1, d2, d3 = [{k: my_dict[k] for k in g} for _, g in groupby(sorted(my_dict, key=key), key=key)] 

Ce genre et regroupe les clés de dictionnaire par une séquence finale de chiffres et crée une liste de dictionnaires séparés des groupes résultants.

+0

Est-il possible d'obtenir la sortie dans 3 dictionnaires différents? Maintenant, nous les obtenons en tant que sous-répertoires –

+0

Yup, vous pouvez faire multi-affectation. Mise à jour ma réponse ... – schwobaseggl

+0

Merci, il a créé 3 dictionnaires. –

0

Si vous voulez dict séparé de chaque résultat groupé alors vous pouvez utiliser le générateur:

my_dict = { 
    'name1': 'abc', 'job1': 'xyz', 'pos1': 'tak', 'phone1': 12345, 
    'name2': 'pqr', 'job2': 'ftr', 'pos2': 'lkj', 'phone2': 27654, 
    'name3': 'swq', 'job3': 'nme', 'pos3': 'mnb', 'phone3': 98421, 
    'bad': 'bad_data', 
} 
group_dict=dict() 
for key,value in my_dict.items(): 
    if key[-1] not in group_dict: 
     group_dict[key[-1]]=[(key,value)] 
    else: 
     try: 
      group_dict[key[-1]].append((key,value)) 
     except keyError: 
      pass 

new_dict={} 

def groups(x): 
    for key,value in x.items(): 
     yield {x[0]: x[1] for x in value} 

new=groups(group_dict) 

print(new.__next__()) 
print(new.__next__()) 
print(new.__next__()) 
print(new.__next__()) 

Sortie:

{'bad': 'bad_data'} 
{'pos2': 'lkj', 'name2': 'pqr', 'job2': 'ftr', 'phone2': 27654} 
{'pos1': 'tak', 'name1': 'abc', 'phone1': 12345, 'job1': 'xyz'} 
{'pos3': 'mnb', 'phone3': 98421, 'job3': 'nme', 'name3': 'swq'} 

Si vous voulez que tous les résultats par une impression alors:

print(list(groups(group_dict))) 

[{'bad': 'bad_data'}, {'pos2': 'lkj', 'name2': 'pqr', 'job2': 'ftr', 'phone2': 27654}, {'pos1': 'tak', 'name1': 'abc', 'phone1': 12345, 'job1': 'xyz'}, {'pos3': 'mnb', 'phone3': 98421, 'job3': 'nme', 'name3': 'swq'}]