Feb 3, 2013

Merging dictionaries in Python with lists within

Because I have just set out to program in Python at work (in depth), I am going to write down on my blog those interesting things that I have to work out related to this activity.

And for example, this week I had to cope a curious problem about merging dictionaries with any kind of element within, such as lists or other dictionaries. Browsing the Internet, I was able to find some functions to combine dictionaries, but the problem was that those methods did not take into account the option of having lists inside.

So in order to get over this issue, I had to develop the following two recursive methods.

def merge_dict(dict1, dict2):   
    if isinstance(dict1, dict) and isinstance(dict2, dict):
        for k, v in dict2.iteritems():
            if k not in dict1:
                dict1[k] = v
            else:
                dict1[k] = merge_dict(dict1[k], v)
    elif isinstance(dict1, list) and isinstance(dict2, list):
        dict1 = merge_list(dict1, dict2)
    elif dict2 == None:
        return dict1
    else:
        return dict2
        
    return dict1

def merge_list(list1, list2):
    if isinstance(list1, list) and isinstance(list2, list):
        for i, item in enumerate(list2):
            if len(list1) > i:
                if isinstance(list1[i], dict) and isinstance(item, dict):
                    list1[i] = merge_dict(list1[i], item)
                elif isinstance(list1[i], list) and isinstance(item, list):
                    list1[i] = merge_list(list1[i], item)
                else:
                    list1[i] = item
            else:
                list1.append(list2[i])
    elif isinstance(list1, dict) and isinstance(list2, dict):
        list1 = merge_dict(list1, list2)
    else:
        return list2

    return list1


As you can see in the above code, the method merge_dict loops through the dictionary and if it comes across a list, it will have a function able to merge the list. Also say that dict2 and list2 will have more priority that dict1 and list1 respectively.

Let's see an example where there are a couple of dictionaries with several elements within.

dict1 = {"country": [{"name": "Spain", "capital": "Madrid"}, {"name": "France"}]}
dict2 = {"country": [{"name": "Germany"}], "continent": "Europe"}

print merge_dict(dict1, dict2)


This is the output for the preceding script.

$ python test.py 

{'country': [{'name': 'Germany', 'capital': 'Madrid'}, {'name': 'France'}], 'continent': 'Europe'}


7 comments: