【问题标题】:How to merge arbitrary number of dictionaries and concatenating values with common keys如何合并任意数量的字典并使用公共键连接值
【发布时间】:2020-05-03 16:23:26
【问题描述】:

假设你有以下字典

dict1 = {'a': 'a'}
dict2 = {'a':'b', 'c':'d' , 'f':'w', 'r':' not unique' }
dict3 = {'a': 'c', 'c':'e'}
dict4 = {'a': 'd', 'c':'e', 'f':'r'}
dict5 = {'r': 'x', 'y':'only unique', 'f':'r'}

预期结果如下:

{'y': 'only unique', 'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex'}

您希望在它们出现时以特定顺序合并它们。如果密钥重复,则需要连接结果。用例是 10K 提交。你经常会发现这个

Column X Column X+1
(123)

当数字是(123)时

【问题讨论】:

    标签: python python-3.x dictionary merge mergeddictionaries


    【解决方案1】:

    我试过了,效果很好

    # helper functions
    def string_comprehension(array_like,separator,separate_chars=False):
    
        if not isinstance(array_like,list):
            array_like = to_list(array_like)
    
        if separate_chars:
            result = ''.join(separator.join(map(str, x)) for x in array_like)
        else:
            result = separator.join(str(x) for x in array_like)
        return result
    
    
    def to_list(var):
    
        a = []
    
        if islist(var): return var
        else: return [var]
    
    def merge_concatenate_dicts(dict_list, separator = ''):
    
        def update_common_dict(local_common_keys,global_common_dict,index_list):
            for key in list(local_common_keys):
                if key in global_common_dict.keys():
                    current_indices = to_list(global_common_dict.get(key))
                    new_indices = sorted(list(set.union(set(current_indices),
                                    set(index_list)))) 
                    common_keys_dict.update( { key: new_indices} )
                else:
                    common_keys_dict.update( { key: index_list} )
            return global_common_dict
    
    
        common_keys_dict = {}
    
        dict_combination = it.combinations(dict_list,2)
    
        disjoint_keys = []
    
        for d_combine in dict_combination:
    
            index_list = sorted([dict_list.index(d_combine[0]),dict_list.index(d_combine[1])])
    
            keys_dict1 = list(d_combine[0].keys())
            keys_dict2 = list(d_combine[1].keys())
    
    
            common_keys = set.intersection( set(keys_dict1), 
                set(keys_dict2))
    
            if common_keys_dict:
                all_common_keys = list(set.union(
                        common_keys,
                        set(list(common_keys_dict.keys())
                    )))
            else: all_common_keys = list(common_keys)        
    
            all_keys = list(reduce(set.union,
                map(set,[keys_dict1, keys_dict2] )))
    
            disjoint_local             = [k for k in all_keys if k not in all_common_keys]
            disjoint_universe          = list(set.union(set(disjoint_local), set(disjoint_keys)))
    
            disjoint_keys              = [k for k in disjoint_universe if k not in all_common_keys]
    
            common_keys_dict = update_common_dict(local_common_keys = common_keys,
                global_common_dict = common_keys_dict, index_list = index_list  )
    
        merged_dicts = {}
    
        for k_disjoint in disjoint_keys:
            for d in dict_list:
                if k_disjoint in d:
                    merged_dicts.update({k_disjoint : d.get(k_disjoint)})
                    break    
    
        for k_common in common_keys_dict.keys():
            dict_merge_list = [d.get(k_common) for idx,d in enumerate(dict_list) if idx in common_keys_dict.get(k_common)]
            merged_val      =  string_comprehension(array_like=dict_merge_list, separator=  separator)  
            merged_dicts.update( {k_common: merged_val} )
    
        return merged_dicts
    
    
    
    dict1 = {'a': 'a'}
    dict2 = {'a':'b', 'c':'d' , 'f':'w', 'r':' not unique' }
    dict3 = {'a': 'c', 'c':'e'}
    dict4 = {'a': 'd', 'c':'e', 'f':'r'}
    dict5 = {'r': 'x', 'y':'only unique', 'f':'r'}
    
    result = merge_concatenate_dicts([dict1,dict2,dict3,dict4,dict5])
    
    print(result)
    

    产量

    {'y': 'only unique', 'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex'}
    

    【讨论】:

      【解决方案2】:

      您可以在此处使用collections.defaultdict

      from collections import defaultdict
      dict1 = {'a': 'a'}
      dict2 = {'a':'b', 'c':'d' , 'f':'w', 'r':' not unique' }
      dict3 = {'a': 'c', 'c':'e'}
      dict4 = {'a': 'd', 'c':'e', 'f':'r'}
      dict5 = {'r': 'x', 'y':'only unique', 'f':'r'}
      
      def merge(*dicts):
          out=defaultdict(str)
          for d in dicts:
              for k,v in d.items():
                  out[k]+=v
          return out #The return type is defaultdict if you want dict then use `return dict(out)`
      
      merge(dict1,dict2,dict3,dict4,dict5)
      # defaultdict(<class 'str'>, {'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex', 'y': 'only unique'})
      
      #When `return dict(out)`
      # {'a': 'abcd', 'c': 'dee', 'f': 'wrr', 'r': ' not uniquex', 'y': 'only unique'}
      

      【讨论】:

      • 谢谢,这是一个更简洁的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 2015-04-22
      • 1970-01-01
      • 2015-07-28
      • 2017-11-07
      • 2020-04-24
      • 1970-01-01
      相关资源
      最近更新 更多