this is actually quite tricky - particularly if you want a useful error message when things are inconsistent, while correctly accepting duplicate but consistent entries (something no other answer here does....)
assuming you don't have huge numbers of entries a recursive function is easiest:
def merge(a, b, path=None):
"merges b into a"
if path is None: path = []
for key in b:
if key in a:
if isinstance(a[key], dict) and isinstance(b[key], dict):
merge(a[key], b[key], path + [str(key)])
elif a[key] == b[key]:
pass # same leaf value
else:
raise Exception('Conflict at %s' % '.'.join(path + [str(key)]))
else:
a[key] = b[key]
return a
# works
print(merge({1:{"a":"A"},2:{"b":"B"}}, {2:{"c":"C"},3:{"d":"D"}}))
# has conflict
merge({1:{"a":"A"},2:{"b":"B"}}, {1:{"a":"A"},2:{"b":"C"}})
note that this mutates a
- the contents of b
are added to a
(which is also returned). if you want to keep a
you could call it like merge(dict(a), b)
.
agf pointed out (below) that you may have more than two dicts, in which case you can use:
reduce(merge, [dict1, dict2, dict3...])
where everything will be added to dict1.
[note - i edited my initial answer to mutate the first argument; that makes the "reduce" easier to explain]
ps in python 3, you will also need from functools import reduce
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…