How to sum dict elements
在python中,我有口述清单:
1 | dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}] |
我想要一个包含所有口述总和的最终口述。即结果为:
注意:列表中的每个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时,利用
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。