web-dev-qa-db-fra.com

Fusion de listes de valeurs de dictionnaire en python

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}
13
branwen85

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]}
13
Martijn Pieters

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]}
0
HBS

Numéro et clés du dictionnaire arbitraire

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.

0
jpp