J'essaie de fusionner trois dictionnaires, qui ont tous les mêmes clés et des listes de valeurs ou des valeurs uniques.
one={'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
two={'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5]}
three={'a': 1.2, 'c': 3.4, 'b': 2.3}
Ce dont j'ai besoin, c'est que tous les éléments des valeurs soient ajoutés à une liste.
result={'a': [1, 2, 2.4, 3.4, 1.2], 'c': [5, 6, 5.6, 7.6, 2.3], 'b': [3, 4, 3.5, 4.5, 3.4]}
J'ai essayé plusieurs choses, mais la plupart ont placé les valeurs dans des listes imbriquées. Par exemple.
out=dict((k, [one[k], two.get(k), three.get(k)]) for k in one)
{'a': [[1, 2], [2.4, 3.4], 1.2], 'c': [[5, 6], [5.6, 7.6], 3.4], 'b': [[3, 4], [3.5, 4.5], 2.3]}
J'ai essayé de le mettre à jour en parcourant les valeurs:
out.update((k, [x for x in v]) for k,v in out.iteritems())
mais les résultats étaient exactement les mêmes. J’ai essayé d’ajouter simplement les listes, mais comme le troisième dictionnaire n’a qu'un flottant, je n’ai pas pu le faire.
check=dict((k, [one[k]+two[k]+three[k]]) for k in one)
J'ai donc essayé d'ajouter d'abord les listes avec les valeurs un et deux, puis d'ajouter la valeur trois. L'ajout des listes a bien fonctionné, mais lorsque j'ai essayé d'ajouter le float du troisième dictionnaire, la valeur entière est soudainement passée à "Aucun".
check=dict((k, [one[k]+two[k]]) for k in one)
{'a': [[1, 2, 2.4, 3.4]], 'c': [[5, 6, 5.6, 7.6]], 'b': [[3, 4, 3.5, 4.5]]}
new=dict((k, v.append(three[k])) for k,v in check.items())
{'a': None, 'c': None, 'b': None}
En one-liner, avec une compréhension du dictionnaire:
new = {key: value + two[key] + [three[key]] for key, value in one.iteritems()}
Cela crée de nouvelles listes, en concaténant la liste de one
avec la liste correspondante de two
, en plaçant la valeur unique de three
dans une liste temporaire pour faciliter la concaténation.
Ou avec une boucle for
mettant à jour one
sur place:
for key, value in one.iteritems():
value.extend(two[key])
value.append(three[key])
Ceci utilise list.extend()
pour mettre à jour la liste d'origine sur place avec la liste de two
et list.append()
pour ajouter la valeur unique de three
.
Où tu t'es trompé:
votre première tentative crée une nouvelle liste avec les valeurs de one
, two
et three
imbriquées au lieu de concaténer les listes existantes. Votre tentative de nettoyage a simplement copié ces listes imbriquées.
Votre deuxième tentative n'a pas fonctionné car la valeur dans three
n'est pas une liste et n'a donc pas pu être concaténée. J'ai créé une nouvelle liste juste pour cette valeur.
Votre dernière tentative n'aurait pas dû utiliser list.append()
dans une expression de générateur, car vous stockez la valeur return de cette méthode, qui est toujours None
(sa modification est stockée directement dans v
et la liste n'a pas besoin d'être renvoyée).
Démo de la première approche:
>>> one={'a': [1, 2], 'c': [5, 6], 'b': [3, 4]}
>>> two={'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5]}
>>> three={'a': 1.2, 'c': 3.4, 'b': 2.3}
>>> {key: value + two[key] + [three[key]] for key, value in one.iteritems()}
{'a': [1, 2, 2.4, 3.4, 1.2], 'c': [5, 6, 5.6, 7.6, 3.4], 'b': [3, 4, 3.5, 4.5, 2.3]}
Voir cette aide ou pas:
>>> dic={}
>>> k=[]
>>> for i in 'abc':
k=one[i]+two[i]
k.append(three[i])
dic[i]=k
>>> dic
{'c': [5, 6, 5.6, 7.6, 3.4], 'a': [1, 2, 2.4, 3.4, 1.2], 'b': [3, 4, 3.5, 4.5, 2.3]}
Les problèmes liés à votre tentative sont traités dans La solution de @MartijnPieters .
Pour une solution généralisée , envisagez d'utiliser itertools.chain
pour chaîner plusieurs dictionnaires. Vous pouvez également utiliser un defaultdict
pour le cas plus général où vous ne trouvez pas les mêmes clés dans chaque dictionnaire.
from collections import defaultdict
from itertools import chain
from operator import methodcaller
# dictionaries with non-equal keys, values all lists for simplicity
one = {'a': [1, 2], 'c': [5, 6], 'b': [3, 4], 'e': [6.2]}
two = {'a': [2.4, 3.4], 'c': [5.6, 7.6], 'b': [3.5, 4.5], 'f': [1.3]}
three = {'a': [1.2], 'c': [3.4], 'b': [2.3], 'e': [3.1]}
# initialise defaultdict of lists
dd = defaultdict(list)
# iterate dictionary items
dict_items = map(methodcaller('items'), (one, two, three))
for k, v in chain.from_iterable(dict_items):
dd[k].extend(v)
print(dd)
# defaultdict(list,
# {'a': [1, 2, 2.4, 3.4, 1.2],
# 'b': [3, 4, 3.5, 4.5, 2.3],
# 'c': [5, 6, 5.6, 7.6, 3.4],
# 'e': [6.2, 3.1],
# 'f': [1.3]})
Remarque: defaultdict
est une sous-classe de dict
. Il n'est donc généralement pas nécessaire de convertir le résultat en un dict
régulier.