简体   繁体   中英

Merging multiple dictionaries in python

I've few dictionaries as follows:

{"item1": {"item2": "300"}}
{"item1": {"item3": {"item4": "400"}}}
{"item1": {"item3": {"item6": "16"}}}
{"item1": {"item7": "aaa"}}
{"item1": {"item8": "bbb"}}
{"item1": {"item9": {"item10" : "2.2"}}}
{"item1": {"item9": {"item11" : "xxx"}}}

I want to merge these dictionaries as follows

{
  "item1": {
    "item2": "300",
    "item3": {
      "item4": "400",
      "item6": "16"
     },
    "item7": "aaa",
    "item8": "bbb",
    "item9": {
      "item10": "2.2",
      "item11": "xxx"
     }
  }
}

item1 is the first key in all dictionaries whereas the nested keys will vary. If there is same nested dictionary within a dictionary in two dictionaries the keys has to be merged (eg: item3 in dictionary 1 and 2). How can i achieve this?

dico_list=[{"item1": {"item2": "300"}}, {"item1": {"item3": {"item4": "400"}}}, {"item1": {"item3": {"item6": "16"}}}, {"item1": {"item7": "aaa"}}, {"item1": {"item8": "bbb"}}, {"item1": {"item9": {"item10" : "2.2"}}}, {"item1": {"item9": {"item11" : "xxx"}}}]

def merge(merge_dico,dico_list):
    for dico in dico_list:
        for key,value in dico.items():
            if type(value)==type(dict()):
                merge_dico.setdefault(key,dict())
                merge(merge_dico[key],[value])
            else:
                merge_dico[key]=value
    return merge_dico

print(merge(dict(),dico_list))
#{'item1': {'item7': 'aaa', 'item9': {'item11': 'xxx', 'item10': '2.2'}, 'item8': 'bbb', 'item3': {'item4': '400', 'item6': '16'}, 'item2': '300'}}

I think this is easiest to do with a recursive helper function:

def merge_dict_into(target, d):
    for key, value in d:
        if isinstance(value, dict):
            recursive_target = target.setdefault(key, {})
            # if not isintance(recursive_target, dict): raise ValueError
            merge_dict_into(recursive_target, value)
        else:
            # if key in target: raise ValueError
            target[key] = value

def merge_dicts(dicts):
    target = {}
    for d in dicts:
        merge_dict_into(target, d)
    return target

I'm not sure how you want to handle dictionaries that have conflicts. For example, merging {"a": 0} with {"a": 1} or {"a": {"b": 2}} . The code above allows a non-dict value to overwrite a previous value, but it will fail if a dictionary tries to replace a non-dictionary. You can uncomment the error checking lines to make any conflict raise an exception, or perhaps write your own error handling logic that resolves the conflicts.

Similar as the others, using a recursive function, however also checks if duplicate values exists in the tree:

from pprint import pprint

dicts = [{"item1": {"item2": "300"}},
         {"item1": {"item3": {"item4": "400"}}},
         {"item1": {"item3": {"item6": "16"}}},
         {"item1": {"item7": "aaa"}},
         {"item1": {"item8": "bbb"}},
         {"item1": {"item9": {"item10" : "2.2"}}},
         {"item1": {"item9": {"item11" : "xxx"}}},]


def walk_tree(fill_dict, mydict):
    for key, val in mydict.iteritems():
        if isinstance(val, dict):
            if key not in fill_dict.keys():
                fill_dict[key] = {}
            walk_tree(fill_dict[key], val)

        else:
            if key in fill_dict.keys():
                raise(StandardError, 'Duplicate')
            fill_dict[key] = val


dicts_total = {}

for mydict in dicts:
    walk_tree(dicts_total, mydict)


pprint(dicts_total)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM