关于python:如何对dict元素求和

How to sum dict elements

在python中,我有口述清单:

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

我想要一个包含所有口述总和的最终口述。即结果为:{'a':5, 'b':7}

注意:列表中的每个dict都将包含相同数量的键、值对。


您可以使用Collections.Counter

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

或者,如果您更喜欢一行:

1
functools.reduce(operator.add, map(collections.Counter, dict1))


有点难看,但只有一行:

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


当添加多个dict时,利用sum()应该可以获得更好的性能。

1
2
3
4
5
6
>>> 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}

添加Stephan的建议

1
2
3
4
>>> {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代码读起来非常好


这可能有助于:

1
2
3
4
5
6
7
8
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}

下面的代码显示了一种方法:

1
2
3
4
5
6
7
8
9
10
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

此输出:

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

如你所愿。

或者,受克里斯启发,更好但仍然可读:

1
2
3
4
5
6
7
8
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:-)


我对建议的计数器的性能很感兴趣,大列表的约简和方法。也许还有人对此感兴趣。您可以在这里查看:https://gist.github.com/torstenrudolf/277e98df296f23f921c

我测试了这组词典的三种方法:

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

求和法的性能最好,其次是约简法,计数器法最慢。下面显示的时间以秒为单位。

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

但这取决于字典中元素的数量。求和法比减法慢。

1
2
3
4
5
6
7
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}


这是一个合理而美丽的。

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


在python 2.7中,可以用collections.counter对象替换dict。这支持计数器的加和减。


另一个单线解决方案

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

这只创建一个计数器,将其用作累加器,并最终转换回dict。