在Python中,我有一个字典列表:
dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
我想要一个最终的字典,其中包含所有字典的总和。
即结果将为:{'a':5, 'b':7}
注:列表中的每个字典都包含相同数量的键值对。
在Python中,我有一个字典列表:
dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
我想要一个最终的字典,其中包含所有字典的总和。
即结果将为:{'a':5, 'b':7}
注:列表中的每个字典都包含相同数量的键值对。
counter = collections.Counter()
for d in dict1:
counter.update(d)
或者,如果你更喜欢一行代码:
functools.reduce(operator.add, map(collections.Counter, dict1))
dictf = reduce(lambda x, y: dict((k, v + y[k]) for k, v in x.iteritems()), dict1)
dictf = reduce(lambda x, y: dict((k, v + y.data[k]) for k, v in x.data.iteritems()), dict1
- carl如果要添加多个字典,利用sum()
应该可以获得更好的性能。
>>> 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 的建议
>>> {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}
我觉得Stephan的Python2.7代码版本写得非常流畅
map
和 itemgetter
而不是在内部循环中使用列表推导式(即 dict((k, sum(d[k] for d in dict1)) for k in dict1[0])
)的原因是什么? - stephan{k: sum(d[k] if type(d[k]) in (int, float) else 0 for d in dict1) for k in dict1[0]}
。 - ygbr这可能有所帮助:
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}
您也可以使用pandas的sum函数计算总和:
import pandas as pd
# create a DataFrame
df = pd.DataFrame(dict1)
# compute the sum and convert to dict.
dict(df.sum())
{'a': 5, 'b': 7}
它也适用于浮点数:
dict2 = [{'a':2, 'b':3.3},{'a':3, 'b':4.5}]
dict(pd.DataFrame(dict2).sum())
{'a': 5.0, 'b': 7.8}
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
{'a': 5, 'b': 7}
如你所愿。
或者,受kriss启发,更好但仍易读:
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的日子 :-)
for
循环简化为 final={}.fromkeys(dict1[0],0)
。或者这就是 "可读性" 所指的吗? :) - John La Rooyfinal.get(k,0) + d[k]
替换final[k] + d[k]
——如果键不存在,我需要从final
字典中获取默认值——我知道它对于d
是存在的。 - paxdiablofinal = dict((k, v + final.get(k, 0)) for k, v in d.iteritems())
代替内部循环。 - kriss我对大型列表的计数器、缩减和求和方法的性能很感兴趣。也许其他人也有兴趣。 你可以在这里查看:https://gist.github.com/torstenrudolf/277e98df296f23ff921c
我测试了这个字典列表的三种方法:
dictList = [{'a': x, 'b': 2*x, 'c': x**2} for x in xrange(10000)]
sum方法表现最佳,其次是reduce方法,而Counter方法最慢。下面显示的时间单位为秒。
In [34]: test(dictList)
Out[34]:
{'counter': 0.01955194902420044,
'reduce': 0.006518083095550537,
'sum': 0.0018319153785705566}
但这取决于字典中元素的数量。相对于sum方法,reduce方法会更快地变慢。
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}
final = {}
for k in dict1[0].Keys():
final[k] = sum(x[k] for x in dict1)
return final
这里是另一个可行的解决方案(python3),它非常通用,因为它适用于字典、列表和数组。对于非常见元素,原始值将包含在输出字典中。
def mergsum(a, b):
for k in b:
if k in a:
b[k] = b[k] + a[k]
c = {**a, **b}
return c
dict1 = [{'a':2, 'b':3},{'a':3, 'b':4}]
print(mergsum(dict1[0], dict1[1]))
sum(map(collections.Counter, dict1),Counter())
。但我不确定函数式版本创建所有这些Counters()
的相对性能。 - John La Rooycounter
是dict
的一个子类实例,如果提问者想要普通的dict
,可以添加最后一行代码counter = dict(counter)
。 - Duncan