web-dev-qa-db-fra.com

Comment résumer des éléments de dict

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.

32
Nazmul Hasan

Un peu moche, mais un one-liner:

dictf = reduce(lambda x, y: dict((k, v + y[k]) for k, v in x.iteritems()), dict1)
15
carl

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))
42
SiggyF

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

11
John La Rooy

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}
8
Manoj Govindan

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 :-)

5
paxdiablo

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}
4
trudolf

Voici une belle raisonnable.

final = {}
for k in dict1[0].Keys():
    final[k] = sum(x[k] for x in dict1)
return final
2
Kyan

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.

1
Dave Kirby

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.

0
Aaron McMillin