I have been trying to merge these two:
A
{'v1': {'configuration': {'$schema': '...', 'network': {'$schema': '...'}}}}
E
{'v1': {'configuration': {'network': {'entries': {'$schema': '...'}}}}}
The result should be:
{'v1': {'configuration': {'$schema': '...', 'network': {'$schema': '...', 'entries': {'$schema': '...'}}}}}
This is one set of data. So I have other situations where that follow
v1
is not justconfiguration
. All I am trying to do is add in the dict the elements from another dict that it doesn't have. Also the A always has precedent.
I tried using one of the examples: Python merge two lists of dicts, where dict key matches
def merge_list_of_dicts(d1: dict, d2: dict):
def merge(list_of_dicts, current={}):
try:
get_key = lambda d: next(iter(d))
get_value = lambda d: next(iter(d.values()))
for d in list_of_dicts:
key = get_key(d)
value = get_value(d)
if key not in current:
current[key] = value
else:
current[key].update(value)
return current
except:
return current
return merge(d2, merge(d1))
print(merge_list_of_dicts(A, E))
I added the try/exception because without it I get this error: AttributeError: 'str' object has no attribute 'values'
The result is:
{}
I also tried:
def myseconfunc(a, b):
print('===========')
a_keys = set(a.keys())
b_keys = set(b.keys())
commons = a_keys.intersection(b_keys)
#print('commons')
#print(commons)
for common in commons:
if type(a) == dict:
a = myseconfunc(a[common], b[common])
print('common:')
print(common)
print('a:')
print(a)
print('b:')
print(b[common])
a.update(b[common])
return a
But I get this:
{'$schema': '...', 'entries': {'$schema': '...'}, 'network': {'entries': {'$schema': '...'}}, 'configuration': {'network': {'entries': {'$schema': '...'}}}}
For more details here is what the prints look like:
===========
common:
network
a:
{'$schema': '...'}
b:
{'entries': {'$schema': '...'}}
===========
common:
configuration
a:
{'$schema': '...', 'entries': {'$schema': '...'}}
b:
{'network': {'entries': {'$schema': '...'}}}
===========
common:
v1
a:
{'$schema': '...', 'entries': {'$schema': '...'}, 'network': {'entries': {'$schema': '...'}}}
b:
{'configuration': {'network': {'entries': {'$schema': '...'}}}}
===========
I am using: Python 3.9.13
CodePudding user response:
Here is a recursive algorithm that passes your example
import copy
A = {'v1': {'configuration': {'$schema': '...', 'network': {'$schema': '...'}}}}
E = {'v1': {'configuration': {'network': {'entries': {'$schema': '...'}}}}}
expected = {'v1': {'configuration': {'$schema': '...', 'network': {'$schema': '...', 'entries': {'$schema': '...'}}}}}
def safe_update_dict(d_to: dict, d_from: dict, inplace: bool=False):
def fn(d_to: dict, d_from: dict):
for k in d_from:
if k in d_to:
if isinstance(d_to[k], dict):
d_to[k] = fn(d_to[k], d_from[k])
else:
d_to[k] = d_from[k]
return d_to
if inplace:
return fn(d_to, d_from)
return fn(copy.deepcopy(d_to), d_from)
rtn = safe_update_dict(A, E)
print(str(expected) == str(rtn)) # True