【问题标题】:Add elements in a list of dictionaries在字典列表中添加元素
【发布时间】:2011-03-22 22:11:15
【问题描述】:

我有一个很长的字典列表,其中包含字符串索引和整数值。字典中的许多键是相同的,但不是全部。我想生成一个字典,其中键是单独字典中键的并集,值是每个字典中与该键对应的所有值的总和。 (例如,组合字典中键 'apple' 的值将是第一个中 'apple' 的值的总和,加上第二个中的 'apple' 的值的总和,等等)

我有以下,但它相当麻烦,需要 ages 来执行。有没有更简单的方法来达到同样的效果?

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

【问题讨论】:

    标签: python dictionary nested


    【解决方案1】:

    这里有一些微基准表明f2(见下文)可能是一个改进。 f2 使用 iteritems 可以避免在内循环中进行额外的 dict 查找:

    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
    

    【讨论】:

    • 谢谢! f2() 实际上为我的特定应用程序减少了大约 80% 的时间。显然是 YRMV。
    【解决方案2】:

    请改用collections.defaultdict

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

    稍微简单一点。

    【讨论】:

      【解决方案3】:

      这也可能很快,但这确实取决于您的数据。它避免了所有不断变化的字典或额外的列表——只有一组所有键和大量读取:-)

      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 ))
      

      【讨论】:

      • 虽然这使用了更复杂的功能,但我无法想象这会更快(但我可能是错的)。在 OP 的代码中,字典列表只被遍历一次,每个字典也是如此。在您的代码中,每个字典都被遍历一次以创建一组键,然后字典列表被遍历#all_keys 次。
      • Felix Kling:好吧,我刚刚尝试过,当我添加一个迭代器(请参阅修订版 ;-) 以仅在它变得更慢时进行遍历。猜猜这就是问题所在。
      【解决方案4】:

      您可以从 google 的 map-reduce 中获得一些灵感。据我了解,它旨在解决此类问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-03
        • 2013-01-31
        • 2012-12-13
        • 2023-02-05
        • 2020-09-18
        相关资源
        最近更新 更多