字典列表中值的总和

时间:2015-09-22 14:30:11

标签: list python-2.7 dictionary sum

我想获取列表中所有字典中每个键的和值,如果其中一个字典中没有键,则其值被视为0.

假设我有两个词典:

d1 = {'a' : 2, 'b' : 1, 'c' : 1}
d2 = {'a' : 3, 'b' : 1.1, 'd' : 2}
mylist = [d1, d2]

我想定义一个sum函数

>>> sum(mylist)
{'a' : 5, 'b' : 2.1, 'c' : 1, 'd' : 2}

如果我只有两本词典,我可以

>>> for key, value in d2.items():
...    try:
...        d1[key] -= value
...    except KeyError: #if the key isn't in d1
...        d1[key] = -value

>>> d1
{'a' : 5, 'b' : 2.1, 'c' : 1, 'd' : 2}

但这不能扩展到任意数量的词典。

我也试过

>>> {k: sum(e[k] for e in mylist) for k in mylist[0]}
{'a' : 5, 'b' : 2.1, 'c' : 1}

但是这并没有给出第一个列表中不存在的元素的总和(在我的例子中我错过了'd'的总和)。

我可以创建一个包含所有可能键的字典,并将其添加到我的列表前面

>>> d0 = {'a' : 0, 'b' : 0, 'c' : 0, 'd' : 0}
>>> newlist = [d0, d1, d2]
>>> {k: sum(e[k] for e in newlist) for k in newlist[0]}
{'a' : 5, 'b' : 2.1, 'c' : 1, 'd' : 2}

但是创建d0将是乏味的。

我还可以使用Counter

中的collections
>>> counterlist = [Counter(d) for d in mylist]
>>> result = Counter()
>>> for c in counterlist:
...    result.update(c)
>>> dict(result)

但我对来回切换Counter并不太满意。

或者,我可以实现'类似更新'的功能

>>> def add(e, f):
...    for key, value in f.items():
...        try:
...            e[key] -= value
...        except KeyError:
...            e[key] = -value

>>> result = dict()
>>> for d in mylist:
...    add(result, d)
>>> result
{'a' : 5, 'b' : 2.1, 'c' : 1, 'd' : 2}

但这让我觉得我正在重新发明轮子。

有更多的pythonic方式吗?

3 个答案:

答案 0 :(得分:2)

首先获取所有键并从词典列表中设置一个新词典:

d1 = {'a' : 2, 'b' : 1, 'c' : 1}
d2 = {'a' : 3, 'b' : 1.1, 'd' : 2}
mylist = [d1, d2]
sum_dict = dict.fromkeys(set().union(*mylist), 0)

之后,只需迭代字典列表和键即可:

for d in mylist:
    for k in d.keys():
        sum_dict[k] += d[k]

答案 1 :(得分:1)

简单Counter解决方案:

d1 = {'a' : 2, 'b' : 1, 'c' : 1}
d2 = {'a' : 3, 'b' : 1.1, 'd' : 2}
d3 = ...
...
mylist = [d1, d2, d3 , ...]

cnt = Counter()
for _c in mylist:
    cnr += Counter(_c)
print cnr
>> Counter({'a': 5, 'b': 2.1, 'd': 2, 'c': 1})
dict(cnr)
>> {'a': 5, 'b': 2.1, 'd': 2, 'c': 1}

对于非计数器解决方案,您可以使用dict.get

sums = {}
for _dics in mylist:
    for key, val in _dics.items():
        sums[key] = sums.get(key, 0) + val

逻辑很简单,如果key dict中不存在sums,则将其设为0

答案 2 :(得分:0)

基于Christian Stade-Schuldt's answer和Jon Clements'回答,这是我想出的

all_keys = set().union(*mylist)
{k: sum(e[k] for e in mylist) for k in allkeys}