【问题标题】:Fastest way of merging (while preserving values) multiple dictionaries in Python?在 Python 中合并(同时保留值)多个字典的最快方法?
【发布时间】:2019-03-07 02:54:54
【问题描述】:

我搜索了合并字典,但我查看的结果都假设 替换 的值。也就是说,如果你有一个像{'config_prop': 2} 这样的dict,另一个像{'config_prop': 7} 这样的dict,则合并的最终结果是{'config_prop': 7}。我要的是{'config_prop': 9}

我的幼稚方法如下,虽然有效,但速度很慢。

split_output = [{'some_prop': 1}, {'some_prop': 2, 'other_prop': 19}]
combined_output = {}
    for d in split_output:
        if combined_output == {}:
            combined_output = d.copy()
        else:
            for key, value in d.items():
                if key in combined_output:
                    combined_output[key] = combined_output[key] + value  # add to existing val
                else:
                    combined_output[key] = value

我很想听听有关更好的方法的建议。谢谢!

更新:我试过了,但它比我的原始代码慢得多:

final_count = Counter() 
for d in split_output:
    final_count += Counter(d)   
final_output = dict(final_count)

【问题讨论】:

    标签: python dictionary optimization


    【解决方案1】:

    您可以使用以下内容:

    from collections import Counter
    
    A = Counter({'config_prop': 2})
    B = Counter({'config_prop': 7})
    A + B
    

    【讨论】:

    • 嗯...有趣的想法,但它比以前慢得多。我用我尝试过的新代码更新了问题。
    • 我不太确定为什么。但是this 声称计数器是最快的,并解释了可能会减慢的速度。考虑阅读它。
    【解决方案2】:

    可以使用字典理解

    combo = [{'some_prop': 1}, {'some_prop': 2, 'other_prop': 19}]
    
    d = {k: sum([i[k] for i in combo]) if k in combo[0] else i[k] for i in combo for k in i}
    
    {'some_prop': 3, 'other_prop': 19}
    

    【讨论】:

      【解决方案3】:

      我很快介绍了几种不同的方法来解决您的问题:

      combined_output = [{'some_prop': 1}, {'some_prop': 2, 'other_prop': 19}]
      
      # set key or append value to new dictionary object:
      
      def dict_sum(dicts):
          output = {}
          for d in dicts:
              for key, value in d.iteritems():
                  if key in output:
                      output[key] += value
                  else:
                      output[key] = value
           return output
          
      # Implement a reducer function using functools:
      
      from functools import reduce
      
      def reducer(accumulator, element):
          for key, value in element.items():
              accumulator[key] = accumulator.get(key, 0) + value
          return accumulator
          
      # Use a Counter:
      
      from collections import Counter
      
      def sum_dicts_values_by_key(dicts):
          return dict(sum([Counter(x) for x in combined_output], Counter()))
      
      # Using dictionary comprehension:
      
      def sum_dict_comprehension(dicts):
          return {k: sum([i[k] for i in dicts]) 
          if k in dicts[0] else i[k] for i in dicts for k in i}
      

      使用timeit 运行快速基准测试以进行比较:

      res_1 = dict_sum(combined_output)
      1000000 loops, best of 3: 457 ns per loop
      
      res_2 = reduce(reducer, combined_output, {})
      1000000 loops, best of 3: 1.35 µs per loop
      
      res_3 = sum_dicts_values_by_key(combined_output)
      100000 loops, best of 3: 12.8 µs per loop
      
      res_4 = sum_dict_comprehension(combined_output)
      1000000 loops, best of 3: 1.53 µs per loop
      

      【讨论】:

      • 添加了第四种方法来分析字典理解
      • 谢谢,韦斯!很好的答案。我想知道 dict size 是否会影响这一点。就我而言,我有两个字典,每个字典都有超过 400,000 个键值对。
      • dict_sum 方法中似乎有一个错字,它会在一个字典后return
      猜你喜欢
      • 1970-01-01
      • 2013-12-10
      • 2023-03-28
      • 2023-03-30
      • 2016-07-10
      • 2011-11-11
      • 2015-07-03
      • 2019-03-23
      • 2018-05-25
      相关资源
      最近更新 更多