2009-06-10 6 views
7

J'ai une liste de dictionnaires, par exemple:Comment créer une dict unique Python à partir d'une liste de dicts en additionnant des valeurs avec des clés communes?

dictList = [ 
    {'a':3, 'b':9, 'c':4}, 
    {'a':9, 'b':24, 'c':99}, 
    {'a':10, 'b':23, 'c':88} 
] 

Tous les dictionnaires ont les mêmes clés par exemple un, b, c. Je souhaite créer un seul dictionnaire avec les mêmes clés où les valeurs sont les sommes des valeurs avec les mêmes clés de tous les dictionnaires dans la liste originale.

Pour l'exemple ci-dessus, la sortie doit être:

{'a':22, 'b':56, 'c':191} 

Quelle serait la façon la plus efficace de le faire? J'ai actuellement:

result = {} 
for myDict in dictList: 
    for k in myDict: 
     result[k] = result.setdefault(k, 0) + myDict[k] 

Répondre

18

Si tous les dicts ont toutes les clés, vous pouvez le faire comme:

>>> dict((key, sum(d[key] for d in dictList)) for key in dictList[0]) 
{'a': 22, 'b': 56, 'c': 191} 

[Modifier] Si la vitesse est une grande priorité, vous pouvez également raser ~ 20 % (mais au prix d'une meilleure lisibilité) avec les éléments suivants à la place:

import operator, itertools 
dict((key, sum(itertools.imap(operator.itemgetter(key), dictList))) 
     for key in dictList[0]) 

la vitesse dépend de la taille de la dict. Je reçois les horaires suivants pour la liste 3 de l'article original, et pour différentes tailles différentes (créées par mutliplying la liste initiale de 10, 100 ou 1000, etc.):

List Size Original  dict+generator  imap+itemgetter 
     3  0.054   0.090    0.097 
    30  0.473   0.255    0.236 
    300  4.668   1.884    1.529 
    3000  46.668   17.975    14.499 

(Toutes les heures pour 10.000 courses)

Il est donc légèrement plus lent pour seulement 3, mais deux à trois fois plus rapide pour les grandes listes.

+3

+1 et si elles ne sont pas toutes les clés: dict ((clé, somme (d.get (clé, 0) pour d en dictlist)) pour la clé dans dictlist [0])) –

+0

@Nadia: à la fois la réponse de Brian et vos commentaires donnent le même code – uolot

+1

@paffnucy: non, ils ne le font pas/ – SilentGhost

7

essayer.

from collections import defaultdict 
result = defaultdict(int) 
for myDict in dictList: 
    for k in myDict: 
     result[k] += myDict[k] 
+0

+1 pour m'avoir appris encore une autre astuce. – NicDumZ

0

Je ne sais pas comment il se rapporte aux autres réponses vitesse sage, mais il y a toujours

from collections import Counter 
result = sum(map(Counter,dictList),Counter()) 

Counter est une sous-classe de dict et il peut être utilisé à la place de dict dans la plupart des endroits. Si nécessaire, vous pouvez simplement le reconvertir en un dict

result = dict(result) 
Questions connexes