How to merge dictionaries of dictionaries?

后端 未结 29 3211
渐次进展
渐次进展 2020-11-22 05:13

I need to merge multiple dictionaries, here\'s what I have for instance:

dict1 = {1:{\"a\":{A}}, 2:{\"b\":{B}}}

dict2 = {2:{\"c\":{C}}, 3:{\"d\":{D}}
         


        
29条回答
  •  一个人的身影
    2020-11-22 06:12

    from collections import defaultdict
    from itertools import chain
    
    class DictHelper:
    
    @staticmethod
    def merge_dictionaries(*dictionaries, override=True):
        merged_dict = defaultdict(set)
        all_unique_keys = set(chain(*[list(dictionary.keys()) for dictionary in dictionaries]))  # Build a set using all dict keys
        for key in all_unique_keys:
            keys_value_type = list(set(filter(lambda obj_type: obj_type != type(None), [type(dictionary.get(key, None)) for dictionary in dictionaries])))
            # Establish the object type for each key, return None if key is not present in dict and remove None from final result
            if len(keys_value_type) != 1:
                raise Exception("Different objects type for same key: {keys_value_type}".format(keys_value_type=keys_value_type))
    
            if keys_value_type[0] == list:
                values = list(chain(*[dictionary.get(key, []) for dictionary in dictionaries]))  # Extract the value for each key
                merged_dict[key].update(values)
    
            elif keys_value_type[0] == dict:
                # Extract all dictionaries by key and enter in recursion
                dicts_to_merge = list(filter(lambda obj: obj != None, [dictionary.get(key, None) for dictionary in dictionaries]))
                merged_dict[key] = DictHelper.merge_dictionaries(*dicts_to_merge)
    
            else:
                # if override => get value from last dictionary else make a list of all values
                values = list(filter(lambda obj: obj != None, [dictionary.get(key, None) for dictionary in dictionaries]))
                merged_dict[key] = values[-1] if override else values
    
        return dict(merged_dict)
    
    
    
    if __name__ == '__main__':
      d1 = {'aaaaaaaaa': ['to short', 'to long'], 'bbbbb': ['to short', 'to long'], "cccccc": ["the is a test"]}
      d2 = {'aaaaaaaaa': ['field is not a bool'], 'bbbbb': ['field is not a bool']}
      d3 = {'aaaaaaaaa': ['filed is not a string', "to short"], 'bbbbb': ['field is not an integer']}
      print(DictHelper.merge_dictionaries(d1, d2, d3))
    
      d4 = {"a": {"x": 1, "y": 2, "z": 3, "d": {"x1": 10}}}
      d5 = {"a": {"x": 10, "y": 20, "d": {"x2": 20}}}
      print(DictHelper.merge_dictionaries(d4, d5))
    

    Output:

    {'bbbbb': {'to long', 'field is not an integer', 'to short', 'field is not a bool'}, 
    'aaaaaaaaa': {'to long', 'to short', 'filed is not a string', 'field is not a bool'}, 
    'cccccc': {'the is a test'}}
    
    {'a': {'y': 20, 'd': {'x1': 10, 'x2': 20}, 'z': 3, 'x': 10}}
    

提交回复
热议问题