【问题标题】:How to create single Python dict from a list of dicts by summing values with common keys?如何通过用公共键对值求和来从字典列表中创建单个 Python 字典?
【发布时间】:2009-06-10 10:01:46
【问题描述】:

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

dictList = [
    {'a':3, 'b':9, 'c':4},
    {'a':9, 'b':24, 'c':99},
    {'a':10, 'b':23, 'c':88}
]

所有字典都有相同的键,例如abc。我希望创建一个具有相同键的字典,其中值是原始列表中所有字典中具有相同键的值的总和。

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

{'a':22, 'b':56, 'c':191}

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

result = {}
for myDict in dictList:
    for k in myDict:
        result[k] = result.setdefault(k, 0) + myDict[k]

【问题讨论】:

    标签: python


    【解决方案1】:

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

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

    [编辑]如果速度是重中之重,您也可以通过以下方式减少约 20%(尽管以牺牲一些可读性为代价):

    import operator, itertools
    dict((key, sum(itertools.imap(operator.itemgetter(key), dictList))) 
          for key in dictList[0])
    

    速度取决于字典的大小。对于原始的 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
    

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

    因此,仅 3 个列表会稍微慢一些,但对于较大的列表,速度会快 2 到 3 倍。

    【讨论】:

    • +1 如果他们没有所有键:dict((key, sum(d.get(key, 0) for d in dictList)) for key in dictList[0]))
    • @Nadia:Brian 的回答和您的评论都给出了相同的代码
    • @Nadia:在这种情况下,您还需要可用键的完整列表 - 如果 dictList[0] 缺少一些,您将无法获得完整的结果。
    • 我猜只是某些事情变得更快/更慢。没有算法改进,因为比率在一定大小之外相当稳定,所以我怀疑这只是一个恒定的因子增益,但更大的设置成本意味着它在小列表上的效果更差。
    • @Jamie:速度增益来自 sum 函数在每次迭代中多次求和的单一应用。此外,dict 仅构建一次,无需在每次迭代时“重新分配”其项目的值。
    【解决方案2】:

    试试这个。

    from collections import defaultdict
    result = defaultdict(int)
    for myDict in dictList:
        for k in myDict:
            result[k] += myDict[k]
    

    【讨论】:

      【解决方案3】:

      我不确定它与其他答案的速度有何关系,但总有

      from collections import Counter
      result = sum(map(Counter,dictList),Counter())
      

      Counterdict 的子类,在大多数情况下可以用来代替dict。如有必要,您可以将其转换回 dict

      result = dict(result)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-04
        • 2014-08-12
        • 2018-04-16
        • 2020-08-05
        • 2023-02-03
        • 1970-01-01
        相关资源
        最近更新 更多