dict1:
{
'level_1_a': 1,
'level_1_b': {
'level_2_a': 2,
'level_2_b': {
'level_3_a': 3
},
'level_2_c': {
'level_3_b': 4
}
}
}
dict2:
{
'level_1_a': 2,
'level_1_b': {
'level_2_a': 2,
'level_2_b': {
'level_3_a': 2
},
'level_2_c': {
'level_3_b': 2
}
}
}
Desired output:
{
'level_1_a': [1,2]
'level_1_b': {
'level_2_a': 2,
'level_2_b': {
'level_3_a': [3,2]
},
'level_2_c': {
'level_3_b': [4,2]
}
}
}
I would like to recursively merge dictionaries without replacing the items of keys and create a list for values if the key existed. The desired output on level_2_a can be a single level list.
CodePudding user response:
Here is a recursive merge:
import collections.abc
def merge(a, b, path=None):
if path is None: path = []
for key in b:
if key in a:
if isinstance(a[key], collections.abc.Mapping) and isinstance(b[key], collections.abc.Mapping):
merge(a[key], b[key], path [str(key)])
elif a[key] != b[key]:
a[key]=[a[key],b[key]]
else:
pass
else:
a[key] = b[key]
return a
With your example:
>>> merge(dict1,dict2)
>>> dict1
{"level_1_a": [1, 2],
"level_1_b": {
"level_2_a": 2,
"level_2_b": {
"level_3_a": [3, 2]},
"level_2_c": {
"level_3_b": [4, 2]}}}
Note: It is destructive to dict a
so make a deep copy if you want the original LH dict.
Note 2: This is super limited in application. Primarily to the example given. Won't work if the values are lists or dicts, etc