Astrea
Astrea

Reputation: 63

Merging Dicts that have Lists of Dicts in Python 2.7

I am trying to merge two dicts in Python that could be The same or one could have far less info

ex.

master = {"a": 5564, "c": [{"d2":6}]}
daily = { "a": 795, "b": 1337, "c": [{"d1": 2,"d2": 2,"d3": [{"e1": 4,"e2": 4}]}]}

They need to be merged so the output is as such

master = { "a": 6359, "b": 1337, "c": [{"d1": 2,"d2": 8,"d3": [{"e1": 4,"e2": 4}]}]}

I took a shot at it though I only ever get returned null. I might be missing something or just way off. I just cant figure it out. Any help would be amazing Thank you.

def merge(master,daily):
    for k, v in daily.items():
        if isinstance(daily[k],list):
            key_check = keyCheck(k, master)
            if key_check:
                merge(master[k],daily[k])
            else :
                master[k] = daily[k]
        else :
            if keyCheck(k, master):
                 master[k] += daily[k]
            else :
                master[k] = daily[k]

keyCheck only checks if a key is in the dictionary so it doesn't throw errors.

Upvotes: 3

Views: 87

Answers (2)

Rockybilly
Rockybilly

Reputation: 4510

Here is a recursive solution. Though it cannot compete with Kasramvd's answer.

def merge(dic1, dic2):

    merged = dict(dic1, **dic2) # Merge dictionaries without adding values. Just exchanging them.
                                # Similar to .update() but does not override subdicts.

    for key in merged:
        if key in dic1 and key in dic2:
            if isinstance(dic1[key], list):
                merged[key] = merge(dic1[key][0], dic2[key][0])
            else:
                merged[key] = dic1[key] + dic2[key]

    return merged

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107287

Here is a one linear using collections.Counter():

>>> from collections import Counter
>> C2 = Counter(daily)
>>> C1 = Counter(master)
>>> 
>>> {k:reduce(lambda x,y : Counter(x)+Counter(y), v) if isinstance(v, list) and k in (C1.viewkeys() & C2) else v for k, v in (C1 + C2).items()}
{'a': 6359, 'c': Counter({'d3': [{'e1': 4, 'e2': 4}], 'd2': 8, 'd1': 2}), 'b': 1337}

First off, you can convert your dictionaries to Counter objects in order to add the values for common keys after summing the counters (that's how Counter's add attribute works), then you can loop over the items and for keys that exist in both counters and their values are lists, you can use the reduce() function to apply the same algorithm to all of the list items too.

If your list contains another nested similar data structure, you can convert this code to a recursive function.

Upvotes: 5

Related Questions