2009-06-10 11 views
7

que tienen una lista de diccionarios, por ejemplo:¿Cómo crear un solo dict de Python a partir de una lista de dictados sumando valores con claves comunes?

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

Todos los diccionarios tienen las mismas claves, por ejemplo, a, b, c. Deseo crear un solo diccionario con las mismas claves donde los valores son las sumas de los valores con las mismas claves de todos los diccionarios en la lista original.

lo tanto, para el ejemplo anterior, la salida debe ser:

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

¿Cuál sería la forma más eficiente de hacer esto? Actualmente tengo:

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

Respuesta

18

Si todos predice tienen todas las claves, se puede hacer esto como:

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

[Editar] Si la velocidad es una gran prioridad, también se pueden reducir la ~ 20 % (aunque a costa de cierta legibilidad) con el siguiente cambio:

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

la velocidad depende del tamaño de la dict. Consigo los siguientes tiempos para la lista 3 artículo original, y para varios tamaños diferentes (creados por mutliplying la lista original de 10, 100 ó 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 

(franja horaria de 10.000 carreras)

Por lo tanto, es un poco más lento por solo 3, pero dos o tres veces más rápido para listas más grandes.

+3

+1 y si no tienen todas las claves: dict ((clave, suma (d.get (clave, 0) para d en dictList)) for key in dictList [0])) –

+0

@Nadia: tanto la respuesta de Brian como tu comentario dan el mismo código – uolot

+1

@paffnucy: no, no lo hacen/ – SilentGhost

7

Pruebe esto.

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

+1 por aprenderme todavía, otro truco. – NicDumZ

0

No estoy seguro de cómo se relaciona con las otras respuestas velocidad prudente, pero siempre hay

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

Counter es una subclase de dict y que puede ser utilizado en lugar del dict en la mayoría lugares. Si es necesario, usted podría convertir de nuevo en un dict

result = dict(result) 
Cuestiones relacionadas