J'ai un dictionnaire qui a un sous-dictionnaire comme celui-ci:

d ={10L: {u'Owner Name': u'abc', u'Email': u'wa@gmail.com', u'Manager Name': u'jhon'}, 12L: {u'Owner Name': u'awdaw', u'Email': u'raghavpatnecha15@gmail.com', u'Manager Name': u'raghav'}}

Donc, quand je fais d[10][Owner Name], je reçois abc. Mais ce modèle se répète, je veux dire que chaque sous-dictionnaire a ces mêmes sous-clés et chaque sous-dictionnaire est de même longueur relativement. Donc, si j'ajoute quelques paramètres en sous-dict avec id=10 alors j'ajouterai les mêmes paramètres aux autres touches.

Maintenant, ma question est chaque fois qu'un élément de mon sous-dict augmente, je dois faire une liste vide et ajouter ses valeurs à cette liste en:

def getcontacts():
    id = [10, 12]
    Owner_names = []
    Emails = []
    Manager_Names = []  # to add more columns just add an empty list
    for j in id:
        Owner_names.append(d[j]['Owner Name'])
        Emails.append(d[j]['Email'])
        Manager_names.append(d[j]['Manager Name'])  # append to list
    return Owner_names, Emails, Manager_Names

names, emails, managers = get_contacts()

Au début, je pensais que c'était une bonne approche, mais comme les éléments de mon sous-dictionnaire augmentent, je dois faire une liste vide et l'ajouter et la renvoyer.

Existe-t-il un moyen d'automatiser ce processus. Donc, si j'ai un nom de sous-clé Product Name, ma fonction pourrait automatiquement créer une liste vide Product_Names et l'ajouter comme Product_names.append(d[j]['Product Name']) puis la renvoyer lorsque j'appelle get contacts par:

Owner_names, emails, Manager_Name, Product Names = get_contacts().

Est-il possible où je pourrais écrire une fonction qui:

  1. Comptez les sous-clés dans mon dictionnaire et faites une liste vide en mettant s comme post-fix.

  2. Ajoutez les valeurs respectives à la liste et ajoutez-la à l'instruction de retour.

Mettre à jour

La solution defaultdict sera-t-elle toujours utile si je veux avoir le contrôle sur les valeurs à utiliser. Actuellement, je fais ceci:

for name, email, manager in zip(names, emails, managers):
         print name, email , manager
         message = message_template.substitute(PERSON_NAME=name.title(),MANAGER_NAME=manager.title())

Disons que j'ai deux listes:

l1 = [u'abc', u'awdaw']
l2 = [u'jhon', u'raghav']
for name1,name2 in zip(l1,l2):
    print name1, name2

Mais je ne peux pas compresser un dictionnaire pour des raisons évidentes. Comment le dict par défaut peut-il m'aider à utiliser les valeurs que je souhaite utiliser. Donc, je ne veux pas inclure Owner_Name je voudrais simplement sauter cela dans cette ligne:

message = message_template.substitute(MANAGER_NAME=manager.title())
2
Raghav Patnecha 11 avril 2018 à 14:25

3 réponses

Meilleure réponse

Solution simple: au lieu de renvoyer un tuple de listes, renvoyez un dict de listes où les clés sont les clés subdictées et les valeurs les listes des valeurs collectées:

from collections import defaultdict

def get_contacts():
    id = [10, 12]
    results = defaultdict(list)
    for j in id:
        obj = d[j]
        for key, value in obj.items():
            results[key].append(value)
    return results

results = get_contacts()
for k, v in results.items():
    print("{} : {}".format(k, v))

En règle générale: lorsque vous pensez avoir besoin de "noms dynamiques", vous voulez vraiment un dict.

ÉDITER:

names, emails, managers = get_contacts()
for name, email, manager in zip(names, emails, managers):
    # ...

=>

results = get_contacts()
names, emails, managers = results["Owner Name"], results['Manager Name'], results["Email"]
for name, email, manager in zip(names, emails, managers):
    # ...
2
bruno desthuilliers 11 avril 2018 à 12:33
    d ={10: {'Owner Name': 'abc', 'Email': 'wa@gmail.com', 'Manager Name': 'jhon'}, 
        12: {'Owner Name': 'awdaw', 'Email': 'raghavpatnecha15@gmail.com', 'Manager Name': 'raghav'}}
    from collections import defaultdict
    def get_contacts():
        data = defaultdict(list)
        for key, val in d.items():
            for key1, val1 in val.items():
                data[key1 + 's'].append(val1)
        return data.values()
    names, emails, managers = get_contacts()
    >>>print(names, emails, managers)
       (['abc', 'awdaw'],['wa@gmail.com', 'raghavpatnecha15@gmail.com'],
        ['jhon', 'raghav'])
-1
Pradam 11 avril 2018 à 11:38
data ={10L: {u'Owner Name': u'abc', u'Email': u'wa@gmail.com', u'Manager Name': u'jhon'}, 
       12L: {u'Owner Name': u'awdaw', u'Email': u'raghavpatnecha15@gmail.com', u'Manager Name': u'raghav'}}

def get_contact(data, ids):
    ret_data = {}
    for i in ids:
        sub_data = data.get(i)
        for k in sub_data.keys():
            ret_data[k] = ret_data.get(k, [])
            ret_data[k].append(sub_data[k])

    # Doing this will have unordered results so one would have to
    # throw data into an OrderedDict (from a 3rd party lib like boltons)
    # return [ret_data[k] for k in ret_data.keys()]

    # so make sense to return the dict
    return ret_data

Mise à jour: vous souhaitez donc que les données renvoyées soient ordonnées de la manière que vous attendez. Eh bien, vous devez indiquer à vos clés "données" l'ordre dans lequel vous les attendez.

def get_contact(data, ids):
ret_data = {}
for i in ids:
    sub_data = data.get(i)
    for k in sub_data.keys():
        ret_data[k] = ret_data.get(k, [])
        ret_data[k].append(sub_data[k])

return [ret_data[k] for k in sorted(ret_data.keys())]
0
Will 11 avril 2018 à 12:32