57 votes

fusion de plusieurs dictionnaires python

Je dois fusionner une liste de dictionnaire python. Par exemple :

dicts[0] = {'a':1, 'b':2, 'c':3}
dicts[1] = {'a':1, 'd':2, 'c':'foo'}
dicts[2] = {'e':57,'c':3}

super_dict = {'a':[1], 'b':[2], 'c':[3,'foo'], 'd':[2], 'e':[57]}    

J'ai écrit le code suivant :

super_dict = {}
for d in dicts:
    for k, v in d.items():
        if super_dict.get(k) is None:
            super_dict[k] = []
        if v not in super_dict.get(k):
            super_dict[k].append(v)

Peut-on le présenter de manière plus élégante / optimisée ?

Note J'ai trouvé un autre question sur SO mais il s'agit de fusionner exactement 2 dictionnaires.

55voto

senderle Points 41607

Vous pouvez itérer sur les dictionnaires directement -- il n'est pas nécessaire d'utiliser la fonction range . Le site setdefault de dict recherche une clé, et renvoie la valeur si elle est trouvée. Si elle n'est pas trouvée, elle renvoie une valeur par défaut, et affecte également cette valeur par défaut à la clé.

super_dict = {}
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict.setdefault(k, []).append(v)

Vous pouvez également envisager d'utiliser un defaultdict . Cela ne fait qu'automatiser setdefault en appelant une fonction qui renvoie une valeur par défaut lorsqu'une clé n'est pas trouvée.

import collections
super_dict = collections.defaultdict(list)
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict[k].append(v)

En outre, comme Sven Marnach Vous semblez vouloir éviter la duplication des valeurs dans vos listes. Dans ce cas, set vous donne ce que vous voulez :

import collections
super_dict = collections.defaultdict(set)
for d in dicts:
    for k, v in d.iteritems():  # d.items() in Python 3+
        super_dict[k].add(v)

32voto

Steven Rumbalski Points 16838
from collections import defaultdict

dicts = [{'a':1, 'b':2, 'c':3},
         {'a':1, 'd':2, 'c':'foo'},
         {'e':57, 'c':3} ]

super_dict = defaultdict(set)  # uses set to avoid duplicates

for d in dicts:
    for k, v in d.items():  # use d.iteritems() in python 2
        super_dict[k].add(v)

16voto

G_kuldeep Points 301

Vous pouvez utiliser ce comportement de dict. (un peu élégant)

 a = {'a':1, 'b':2, 'c':3}
 b = {'d':1, 'e':2, 'f':3}
 c = {1:1, 2:2, 3:3}
 merge = {**a, **b, **c}
 print(merge) # {'a': 1, 'b': 2, 'c': 3, 'd': 1, 'e': 2, 'f': 3, 1: 1, 2: 2, 3: 3}

et vous êtes prêt à partir :)

14voto

Sven Marnach Points 133943

Fusionner les clés de toutes les dicts, et pour chaque clé assembler la liste des valeurs :

super_dict = {}
for k in set(k for d in dicts for k in d):
    super_dict[k] = [d[k] for d in dicts if k in d]

L'expression set(k for d in dicts for k in d) construit un ensemble de toutes les clés uniques de tous les dictionnaires. Pour chacune de ces clés uniques, nous utilisons la compréhension de liste [d[k] for d in dicts if k in d] pour construire la liste des valeurs de toutes les dicts pour cette clé.

Puisque vous ne semblez avoir qu'un seul unique de chaque clé, vous pouvez utiliser des ensembles à la place :

super_dict = {}
for k in set(k for d in dicts for k in d):
    super_dict[k] = set(d[k] for d in dicts if k in d)

7voto

pbreach Points 4386

Il semble que la plupart des réponses utilisant des compréhensions ne sont pas si lisibles que ça. Au cas où vous vous perdriez dans le fouillis des réponses ci-dessus, voici ce qui pourrait vous être utile (bien qu'extrêmement tard...). Il suffit de boucler sur les éléments de chaque dict et de les placer dans un autre.

super_dict = {key:val for d in dicts for key,val in d.items()}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X