En Python, j'ai une liste de dict:
dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
Je veux un dernier dict qui contiendra la somme de tous les dict. Ie le résultat sera: {'a':5, 'b':7}
N.B: chaque dictionnaire de la liste contiendra le même nombre de paires clé/valeur.
Un peu moche, mais un one-liner:
dictf = reduce(lambda x, y: dict((k, v + y[k]) for k, v in x.iteritems()), dict1)
Vous pouvez utiliser le collections.Counter
counter = collections.Counter()
for d in dict1:
counter.update(d)
Ou, si vous préférez les oneliners:
functools.reduce(operator.add, map(collections.Counter, dict1))
Tirer parti de sum()
devrait améliorer les performances lors de l’ajout de plusieurs dict
>>> dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
>>> from operator import itemgetter
>>> {k:sum(map(itemgetter(k), dict1)) for k in dict1[0]} # Python2.7+
{'a': 5, 'b': 7}
>>> dict((k,sum(map(itemgetter(k), dict1))) for k in dict1[0]) # Python2.6
{'a': 5, 'b': 7}
ajout de la suggestion de Stephan
>>> {k: sum(d[k] for d in dict1) for k in dict1[0]} # Python2.7+
{'a': 5, 'b': 7}
>>> dict((k, sum(d[k] for d in dict1)) for k in dict1[0]) # Python2.6
{'a': 5, 'b': 7}
Je pense que la version du code Python2.7 de Stephan se lit vraiment bien
Cela pourrait aider:
def sum_dict(d1, d2):
for key, value in d1.items():
d1[key] = value + d2.get(key, 0)
return d1
>>> dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
>>> reduce(sum_dict, dict1)
{'a': 5, 'b': 7}
Le code suivant montre une façon de le faire:
dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
final = {}
for k in dict1[0].keys(): # Init all elements to zero.
final[k] = 0
for d in dict1:
for k in d.keys():
final[k] = final[k] + d[k] # Update the element.
print final
Cela génère:
{'a': 5, 'b': 7}
comme vous le souhaitez.
Ou, comme inspiré par le kriss, mieux mais toujours lisible:
dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
final = {}
for d in dict1:
for k in d.keys():
final[k] = final.get(k,0) + d[k]
print final
Je me penche pour l'époque de l'original, lisible en Python :-)
Je me suis intéressé à la performance proposée des méthodes de comptage, de réduction et de somme pour les grandes listes. Peut-être que quelqu'un d'autre est également intéressé par ceci . Vous pouvez jeter un coup d'œil ici: https://Gist.github.com/torstenrudolf/277e98df296f23ff921c
J'ai testé les trois méthodes pour cette liste de dictionnaires:
dictList = [{'a': x, 'b': 2*x, 'c': x**2} for x in xrange(10000)]
la méthode de la somme montre la meilleure performance, suivie de réduire et Counter est la plus lente. Le temps indiqué ci-dessous est en secondes.
In [34]: test(dictList)
Out[34]:
{'counter': 0.01955194902420044,
'reduce': 0.006518083095550537,
'sum': 0.0018319153785705566}
Mais cela dépend du nombre d'éléments dans les dictionnaires. la méthode de la somme ralentira plus vite que la réduction.
l = [{y: x*y for y in xrange(100)} for x in xrange(10000)]
In [37]: test(l, num=100)
Out[37]:
{'counter': 0.2401433277130127,
'reduce': 0.11110662937164306,
'sum': 0.2256883692741394}
Voici une belle raisonnable.
final = {}
for k in dict1[0].Keys():
final[k] = sum(x[k] for x in dict1)
return final
En Python 2.7, vous pouvez remplacer le dict par un collections.Counter object. Ceci prend en charge l'addition et la soustraction de compteurs.
Une autre solution en une ligne
dict(
functools.reduce(
lambda x, y: x.update(y) or x, # update, returns None, and we need to chain.
dict1,
collections.Counter())
)
Cela crée un seul compteur, l’utilise comme un accumulateur et finalement reconvertit en dict.