I have two nested dictionaries and I want to merge them into one (where second dict overrides first dict values). I saw a lot of beautiful solutions for merging "flat" (not nested) dictionaries, e.g.:
dict_result = dict1.copy()
dict_result.update(dict2)
or
dict_result = dict(dict1.items() + dict2.items())
or (my favorit one)
dict_result = dict(d1,**d2)
but couldn't find the most efficient way to merge multi-nested dicts.
I'm trying to avoid recursion. What is your proposition?
Unless the depth of the dictionaries to merge is strictly limited, there's no way to avoid recursion.1) Also, there's no bultin or library function to do this (that is, none that I know of), but it's actually not all that hard. Something like this should do:
def merge(d1, d2):
for k in d2:
if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict):
merge(d1[k], d2[k])
else:
d1[k] = d2[k]
What this does: It iterates the keys in d2
and if the key can also be found in d1
and both are dictionaries, merge those sub-dictionaries, otherwise overwrite the value in d1
with that from d2
. Note that this changes d1
and its sub-dictionaries in place, so you might want to deep-copy it before.
Or use this version to create a merged copy:
def merge_copy(d1, d2):
return {k: merge_copy(d1[k], d2[k]) if k in d1 and isinstance(d1[k], dict) and isinstance(d2[k], dict) else d2[k] for k in d2}
Example:
>>> d1 = {"foo": {"bar": 23, "blub": 42}, "flub": 17}
>>> d2 = {"foo": {"bar": 100}, "flub": {"flub2": 10}, "more": {"stuff": 111}}
>>> merge(d1, d2)
>>> print d1
{'foo': {'bar': 100, 'blub': 42}, 'flub': {'flub2': 10}, 'more': {'stuff': 111}}
1) You can make it iterative, using a stack, but this will only make things more complicated and should only be done to avoid problems with maximum recursive depth.
Modified version of the above merge_copy
function for dicts that can be thought of as merging parent and child where you want the parent to inherit all the values from child to create a new dict.
def merge_copy(child, parent):
'''returns parent updated with child values if exists'''
d = {}
for k in parent:
if k in child and isinstance(child[k], dict) and isinstance(parent[k], dict):
v = merge_copy(child[k], parent[k])
elif k in child:
v = child[k]
else:
v = parent[k]
d[k] = v
return d
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With