'How to 'deep-merge' dicts?
Imagine the following dicts:
a = {'key1': {'subkey1': [1, 2, 3]}}
b = {'key1': {'subkey2': [1, 2, 3]}}
I'd like to merge them to get
c = {'key1': {'subkey1': [1, 2, 3],
'subkey2': [1, 2, 3]}}
Extra nice would be a solution that returns deep-copies from a and b which I can alter without altering a or b.
c = {**a, **b}
looks nice but seems to be the same as c = copy(a).update(b) which returns same as b in my case because key1 gets overwritten by the update.
You can of course do this by hand like this (found in another answer):
def combine_dict(map1: dict, map2: dict):
def update(d: dict, u: dict):
for k, v in u.items():
if isinstance(v, collections.Mapping):
r = update(d.get(k, {}), v)
d[k] = r
else:
d[k] = u[k]
return d
_result = {}
update(_result, map1)
update(_result, map2)
return _result
But we have Python 3.5 now - maybe things have changed?
Solution 1:[1]
You need recursion to accomplish this. Luckily milanboers on GitHub saved us from hours of work and possible brain damage.
def deep_merge(dict1: dict, dict2: dict) -> dict:
""" Merges two dicts. If keys are conflicting, dict2 is preferred. """
def _val(v1, v2):
if isinstance(v1, dict) and isinstance(v2, dict):
return deep_merge(v1, v2)
return v2 or v1
return {k: _val(dict1.get(k), dict2.get(k)) for k in dict1.keys() | dict2.keys()}
a = {'key1': {'subkey1': [1, 2, 3]}}
b = {'key1': {'subkey2': [1, 2, 3]}}
a = deep_merge(a, b)
print(a)
Results in:
{'key1': {'subkey2': [1, 2, 3], 'subkey1': [1, 2, 3]}}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ss1 |
