To pytanie jest stare, ale trafiłem tutaj, szukając rozwiązania „głębokiego scalania”. Powyższe odpowiedzi zainspirowały poniższe. Skończyło się na tym, że napisałem własną, ponieważ we wszystkich testowanych wersjach były błędy. Punktem krytycznym pominiętym było, na jakiejś arbitralnej głębokości dwóch dykt wejściowych, dla jakiegoś klucza k, drzewo decyzyjne, gdy d [k] lub u [k] nie jest dyktem, było błędne.
Ponadto to rozwiązanie nie wymaga rekursji, która jest bardziej symetryczna z tym dict.update()
, jak działa, i zwraca None
.
import collections
def deep_merge(d, u):
"""Do a deep merge of one dict into another.
This will update d with values in u, but will not delete keys in d
not found in u at some arbitrary depth of d. That is, u is deeply
merged into d.
Args -
d, u: dicts
Note: this is destructive to d, but not u.
Returns: None
"""
stack = [(d,u)]
while stack:
d,u = stack.pop(0)
for k,v in u.items():
if not isinstance(v, collections.Mapping):
# u[k] is not a dict, nothing to merge, so just set it,
# regardless if d[k] *was* a dict
d[k] = v
else:
# note: u[k] is a dict
# get d[k], defaulting to a dict, if it doesn't previously
# exist
dv = d.setdefault(k, {})
if not isinstance(dv, collections.Mapping):
# d[k] is not a dict, so just set it to u[k],
# overriding whatever it was
d[k] = v
else:
# both d[k] and u[k] are dicts, push them on the stack
# to merge
stack.append((dv, v))