在2.6中合并n个字典并添加值的最快方法

9

我有一个字典列表,想将它们合并成一个字典,并且将列表中每个字典的值相加。例如:

ds = [{1: 1, 2: 0, 3: 0}, {1: 2, 2: 1, 3: 0}, {1: 3, 2: 2, 3: 1, 4: 5}]

最终结果应该是一个字典:
merged = {1: 6, 2: 3, 3: 1, 4: 5}

我对性能很感兴趣,正在寻找最快的实现方法来合并一个由n个字典组成的列表,并将值相加。一个显然的实现方案是:

from collections import defaultdict

merged = defaultdict(int)

for d in ds:
    for k, v in d.items():
        merged[k] += v

在 Python 2.6 中有更快的方法吗?


不用管了,这不是重复内容,因为这只允许 2.6 版本。 - jamylak
如何对字典元素求和 - ShinTakezou
@user1728853 平均每个字典的大小会有多大? - jamylak
通常情况下,相当小,少于500个项目。 - user1728853
我想不出比你明显的实现更快的方法。 - Pavel Anossov
如果您知道数字的上限,可能使用[0]*n初始化列表会更快。此外,您可以尝试使用.iteritems来查看它是否对您的情况有所帮助,我知道对于非常大的数据它会有帮助,但不确定对于500个项目是否足够大。 - jamylak
1个回答

6

defaultdict 仍然是最快的,我找到了一些加速的方法,如缓存函数名称,现在又发现了另一种显著加速的方法,即仅通过迭代 for k in d 而不是使用 d.items()d.iteritems()

目前为止的一些计时:

from random import randrange
ds = [dict((randrange(1, 1000), randrange(1, 1000)) for i in xrange(500))
      for i in xrange(10000)]

# 10000 dictionaries of approx. length 500

from collections import defaultdict

def merge1(dicts, defaultdict=defaultdict, int=int):
    merged = defaultdict(int)
    for d in dicts:
        for k in d:
            merged[k] += d[k]
    return merged

def merge2(dicts):
    merged = {}
    merged_get = merged.get
    for d in dicts:
        for k in d:
            merged[k] = merged_get(k, 0) + d[k]
    return merged


def merge3(dicts):
    merged = {}
    for d in dicts:
        for k in d:
            merged[k] = merged[k] + d[k] if k in merged else 0
    return merged


from timeit import timeit
for func in ('merge1', 'merge2', 'merge3'):
    print func, timeit(stmt='{0}(ds)'.format(func),
                       setup='from __main__ import merge1, merge2, merge3, ds',
                       number=1)

merge1 0.992541510164
merge2 1.40478747997
merge3 1.23502204889

2
你确定那真的更快吗?(我问这个问题是因为过去我发现对Counter对象求和非常慢。) - DSM
@DSM 不过这并不重要,我认为时间安排在另一个线程中。 - jamylak
我应该提到,我正在使用Python 2.6。 - user1728853
@user1728853,你可能需要尝试这两种优化方案,不过那个线程已经有了时间记录。 - jamylak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接