在字典列表中添加元素

7 投票
4 回答
2925 浏览
提问于 2025-04-16 02:02

我有一个很长的字典列表,每个字典里都有字符串作为键,整数作为值。虽然这些字典里的键有很多是一样的,但并不是所有的键都是相同的。我想生成一个新的字典,这个字典的键是所有字典中键的集合,而对应的值则是每个字典中相同键的值的总和。比如说,在这个新字典中,'apple'这个键的值就是第一个字典中'apple'的值加上第二个字典中'apple'的值,依此类推。

我现在有一个方法可以做到这一点,但这个方法比较麻烦,而且执行起来非常慢。有没有更简单的方法可以达到同样的效果呢?

comb_dict = {}  
for dictionary in list_dictionaries:  
    for key in dictionary:  
        comb_dict.setdefault(key, 0)  
        comb_dict[key] += dictionary[key]  
return comb_dict

4 个回答

1

使用 collections.defaultdict 会更好。

http://docs.python.org/library/collections.html#defaultdict-objects

这样会简单一些。

1

这个方法也可能很快,但其实要看你的数据情况。它避免了使用不断变化的字典或额外的列表——只用一组所有的键,读取的次数很多:-)

from itertools import chain

def union( dict_list ):
    all_keys = set(chain.from_iterable(dict_list))
    for key in all_keys:
        yield key, sum( d.get(key,0) for d in dict_list)

combined = dict(union( dict_list ))
9

这里有一些小测试,显示f2(见下文)可能会更好。f2使用了iteritems,这样可以在内层循环中避免多一次查找字典:

import collections
import string
import random

def random_dict():
    n=random.randint(1,26)
    keys=list(string.letters)
    random.shuffle(keys)
    keys=keys[:n]
    values=[random.randint(1,100) for _ in range(n)]    
    return dict(zip(keys,values))

list_dictionaries=[random_dict() for x in xrange(100)]

def f1(list_dictionaries):
    comb_dict = {}  
    for dictionary in list_dictionaries:  
        for key in dictionary:  
            comb_dict.setdefault(key, 0)  
            comb_dict[key] += dictionary[key]  
    return comb_dict

def f2(list_dictionaries):    
    comb_dict = collections.defaultdict(int)
    for dictionary in list_dictionaries:  
        for key,value in dictionary.iteritems():  
            comb_dict[key] += value
    return comb_dict

def union( dict_list ):
    all_keys = set()
    for d in dict_list:
        for k in d:
            all_keys.add( k )
    for key in all_keys:
        yield key, sum( d.get(key,0) for d in dict_list)

def f3(list_dictionaries):
    return dict(union( list_dictionaries ))

以下是测试结果:

% python -mtimeit -s"import test" "test.f1(test.list_dictionaries)"
1000 loops, best of 3: 776 usec per loop
% python -mtimeit -s"import test" "test.f2(test.list_dictionaries)"
1000 loops, best of 3: 432 usec per loop    
% python -mtimeit -s"import test" "test.f3(test.list_dictionaries)"
100 loops, best of 3: 2.19 msec per loop

撰写回答