如何通过使用公共密钥对值进行求和,从一系列dicts创建单个Python dict?

msa*_*ers 7 python

我有一个词典列表,例如:

dictList = [
    {'a':3, 'b':9, 'c':4},
    {'a':9, 'b':24, 'c':99},
    {'a':10, 'b':23, 'c':88}
]
Run Code Online (Sandbox Code Playgroud)

所有词典都具有相同的键,例如a,b,c.我希望创建一个具有相同键的单个字典,其中值是原始列表中所有字典中具有相同键的值的总和.

所以对于上面的例子,输出应该是:

{'a':22, 'b':56, 'c':191}
Run Code Online (Sandbox Code Playgroud)

这样做最有效的方法是什么?我目前有:

result = {}
for myDict in dictList:
    for k in myDict:
        result[k] = result.setdefault(k, 0) + myDict[k]
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 18

如果所有的词都有所有键,你可以这样做:

>>> dict((key, sum(d[key] for d in dictList)) for key in dictList[0])
{'a': 22, 'b': 56, 'c': 191}
Run Code Online (Sandbox Code Playgroud)

[编辑]如果速度是一个重要的优先事项,你也可以用以下代码减少~20%(虽然以一些可读性为代价):

import operator, itertools
dict((key, sum(itertools.imap(operator.itemgetter(key), dictList))) 
      for key in dictList[0])
Run Code Online (Sandbox Code Playgroud)

速度取决于字典的大小.我得到了原始3项列表的以下时间,以及各种不同的大小(通过将原始列表多出10,100或1000等创建):

List Size   Original      dict+generator       imap+itemgetter
      3      0.054          0.090                0.097
     30      0.473          0.255                0.236
    300      4.668          1.884                1.529
   3000     46.668         17.975               14.499
Run Code Online (Sandbox Code Playgroud)

(10,000次运行的所有时间)

所以它只有3个稍慢,但对于较大的列表来说要慢两到三倍.

  • +1并且如果它们没有所有键:dict((dictList中的键,d(d.get(键,0)表示d中的d))dictList [0]中键的表示) (3认同)
  • @Nadia:在这种情况下,你还需要一个完整的可用键列表 - 如果dictList [0]缺少一些,你将无法获得完整的结果. (3认同)
  • @Jamie:速度增益来自于在每次迭代中通过多次求和的和函数的单次应用.另外,dict仅构建一次,并且不需要在每次迭代时"重新分配"其项目的值. (3认同)

S.L*_*ott 7

试试这个.

from collections import defaultdict
result = defaultdict(int)
for myDict in dictList:
    for k in myDict:
        result[k] += myDict[k]
Run Code Online (Sandbox Code Playgroud)