Как суммировать элементы dict - PullRequest
35 голосов
/ 16 августа 2010

В Python у меня есть список диктов:

dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]

Я хочу один финальный дикт, который будет содержать сумму всех диктов.Т.е. результат будет: {'a':5, 'b':7}

Примечание: каждый дикт в списке будет содержать одинаковое количество пар ключ-значение.

Ответы [ 9 ]

45 голосов
/ 16 августа 2010

Вы можете использовать collection.Counter

counter = collections.Counter()
for d in dict1: 
    counter.update(d)

Или, если вы предпочитаете oneliners:

functools.reduce(operator.add, map(collections.Counter, dict1))
15 голосов
/ 16 августа 2010

Немного некрасиво, но однострочно:

dictf = reduce(lambda x, y: dict((k, v + y[k]) for k, v in x.iteritems()), dict1)
11 голосов
/ 16 августа 2010

Использование sum() должно повысить производительность при добавлении более чем нескольких диктов

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

при добавлении предложения Стефана

>>> {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}

Я думаю, что версия кода Стефана Python2.7 гласиточень мило

8 голосов
/ 16 августа 2010

Это может помочь:

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}
5 голосов
/ 16 августа 2010

Следующий код показывает один из способов сделать это:

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

Это выводит:

{'a': 5, 'b': 7}

по вашему желанию.

Или, как вдохновлено Криссом, лучше, но все же читабельно:

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

Я жажду дней оригинального, читаемого Python: -)

4 голосов
/ 27 мая 2014

Меня заинтересовали показатели работы предложенного счетчика, методы уменьшения и суммирования для больших списков.Может быть, кто-то еще заинтересован в этом.Вы можете посмотреть здесь: https://gist.github.com/torstenrudolf/277e98df296f23ff921c

Я проверил три метода для этого списка словарей:

dictList = [{'a': x, 'b': 2*x, 'c': x**2} for x in xrange(10000)]

метод суммирования показал лучшую производительность, за ним последовало уменьшение и счетчиксамый медленный.Время, показанное ниже, указано в секундах.

In [34]: test(dictList)
Out[34]: 
{'counter': 0.01955194902420044,
 'reduce': 0.006518083095550537,
 'sum': 0.0018319153785705566}

Но это зависит от количества элементов в словарях.метод суммирования будет замедляться быстрее, чем уменьшение.

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}
2 голосов
/ 30 декабря 2015

Вот разумный красивый.

final = {}
for k in dict1[0].Keys():
    final[k] = sum(x[k] for x in dict1)
return final
1 голос
/ 16 августа 2010

В Python 2.7 вы можете заменить dict объектом collection.Counter .Это поддерживает сложение и вычитание счетчиков.

0 голосов
/ 29 июля 2016

Еще одно решение на одну строку

dict(
    functools.reduce(
        lambda x, y: x.update(y) or x,  # update, returns None, and we need to chain.
        dict1,
        collections.Counter())
)

Это создает только один счетчик, использует его в качестве аккумулятора и, наконец, преобразует обратно в dict.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...