Как объединить несколько dicts, суммируя значения общих ключей (и сохраняя значения со значением 0) в Python?

Учитывая три слова d1, d2 и d3:

d1

{'a':1,'b':2,'c':3, 'd':0)

d2

{'b':76}

d3

{'a': 45, 'c':0}

Есть несколько ключевых имен, которые являются общими для более чем одного dict (и на самом деле они будут представлять один и тот же объект реальной жизни). Другие, такие как 'd' в d1, существуют только в d2. Я хочу сгруппировать все dicts вместе, сначала сначала суммируя значения общих ключей,, заканчивая:

{'a':46, 'b':78, 'c':3, 'd': 0}

Если бы каждый dict имел одинаковый размер и содержал одни и те же ключи, я мог бы сделать что-то вроде:

summedAndCombined = {}
    for k,v in d1.items():
        summedAndCombined[k] = d1[k]+d2[k]+d3[k]

Но это сломается, как только он достигнет ключа, который находится в d1, но не в других. Как мы это достигаем?

UPDATE

Не дубликат. collections.Counter почти работает, но ключ d отсутствует в результирующем счетчике, если значение ключа d равно нулю, которое выше.

In [128]: d1 = {'a':1,'b':2,'c':3, 'd':0}

In [129]: d2 = {'b':76}

In [130]: d3 = {'a': 45, 'c':0}

In [131]: from collections import Counter

In [132]: Counter(d1) + Counter(d2) + Counter(d3)
Out[132]: Counter({'b': 78, 'a': 46, 'c': 3})

Ответ 1

Вы можете использовать update вместо + с Counter, если вы хотите, чтобы клавиши 0 сохранялись:

>>> c = Counter()
>>> for d in d1, d2, d3:
...     c.update(d)
...     
>>> c
Counter({'b': 78, 'a': 46, 'c': 3, 'd': 0})

(Возможно, это дубликат, но я не могу найти его прямо сейчас.)

Ответ 2

UNTESTED:

def merge_dicts(*dicts):
    res = {}
    for key in set(sum(map(list, dicts), [])):
        res[key] = 0
        for dct in dicts:
            res[key] += dct.get(key, 0)
    return res

Пример использования:

merge_dicts(d1, d2, d3)

Ответ 3

collections.defaultdict на помощь

import collections
d = collections.defaultdict(int)
for thing in [d1, d2, d3]:
    for k, v in thing.items():
        d[k] += v