总结多个python词典的相应元素

时间:2013-10-19 02:36:49

标签: python dictionary zip list-comprehension

我有一组任意数量的等长python词典,带有匹配的键组,如下所示:

{'a':1, 'b':4, 'c':8, 'd':9}

{'a':2, 'b':3, 'c':2, 'd':7}

{'a':0, 'b':1, 'c':3, 'd':4}
...

如何使用相同的键集获取单个字典,但是将值作为字典集中相应元素的总和?换句话说,我想要:

{'a':3, 'b':8, 'c':13, 'd':20}

也许有一个丑陋,复杂的循环结构,但有一种更好的方法来做某些列表/字典理解聪明吗?想想看,我真的不确定如何制作一个丑陋的循环版本,无论如何..

4 个答案:

答案 0 :(得分:15)

collections.Counter()救援; - )

from collections import Counter
dicts = [{'a':1, 'b':4, 'c':8, 'd':9},
         {'a':2, 'b':3, 'c':2, 'd':7},
         {'a':0, 'b':1, 'c':3, 'd':4}]
c = Counter()
for d in dicts:
    c.update(d)

然后:

>>> print c
Counter({'d': 20, 'c': 13, 'b': 8, 'a': 3})

或者你可以将它改回dict:

>>> print dict(c)
{'a': 3, 'c': 13, 'b': 8, 'd': 20}

Counter()所有输入词都是否具有相同的键并不重要。如果你肯定知道他们这样做,你可以尝试荒谬;-)这样的单行:

d = {k: v for k in dicts[0] for v in [sum(d[k] for d in dicts)]}

Counter()更清晰,更快捷,更灵活。但公平地说,这种略显荒谬的单行内容并不那么荒谬:

d = {k: sum(d[k] for d in dicts) for k in dicts[0]}

答案 1 :(得分:2)

如果您只想使用dict,则可以使用此

dicts = [{'a':0, 'b':4, 'c':8, 'd':9},
         {'a':0, 'b':3, 'c':2, 'd':7},
         {'a':0, 'b':1, 'c':3, 'd':4}]

result = {}
for myDict in dicts:
    for key, value in myDict.items():
        result.setdefault(key, 0)
        result[key] += value
print result

<强>输出:

{'a': 0, 'c': 13, 'b': 8, 'd': 20}

答案 2 :(得分:0)

使用 sum 的哨兵值作为 Counter 对象的单行:

>>> from collections import Counter
>>> dicts = [{'a':1, 'b':4, 'c':8, 'd':9},
         {'a':2, 'b':3, 'c':2, 'd':7},
         {'a':0, 'b':1, 'c':3, 'd':4}]
>>> dict(sum(map(Counter, dicts), start=Counter()))
{'a': 3, 'b': 8, 'c': 13, 'd': 20}

答案 3 :(得分:-1)

这是将字典理解itertools.chain.from_iterable()sum()一起使用的替代方法。

在这里,我正在从所有三个字典中创建一个 set 键。然后我在 dictionary comprehension 中迭代这个集合以获得每个 keyvalues 总和。

from itertools import chain

my_dicts = [
    {'a':1, 'b':4, 'c':8, 'd':9},
    {'a':2, 'b':3, 'c':2, 'd':7},
    {'a':0, 'b':1, 'c':3, 'd':4}
]
    
new_dict = {k: sum(dd.get(k, 0) for dd in my_dicts) for k in set(chain.from_iterable(d.keys() for d in my_dicts))}

# where `new_dict` will hold:
#   {
#      'a': 3,  
#      'b': 8,
#      'c': 13,
#      'd': 20
#   }