Reputation: 917
I'd like to combine two nested dictionaries
d1 = {"admin": {"key1": "v2"}}
d2 = {"admin": {"key2": "v3"},
"user": {"something": "else"}}
This should be combine to:
d = {"admin": {"key1": "v2",
"key2": "v3"},
"user": {"something": "else"}}
Is there an easy way to do it other than iterating over the first key?
Upvotes: 3
Views: 723
Reputation: 23711
You can use defaultdict
to have every value of first level as a dict
. After you can use update()
from dict.
>>> from collections import defaultdict
>>> d = defaultdict(dict)
>>> d1 = {"admin": {"key1": "v2"}}
>>> d2 = {"admin": {"key2": "v3"},
... "user": {"something": "else"}}
>>> for dd in [d1,d2]:
... for k,v in dd.items():
... d[k].update(v)
...
>>> d
defaultdict(<type 'dict'>, {'admin': {'key2': 'v3', 'key1': 'v2'}, 'user': {'something': 'else'}})
Or in a more compact form you can use map()
... really I don't like it but is a chance
>>> for dd in [d1,d2]:
... map(lambda x:d[x[0]].update(x[1]),dd.items())
Upvotes: 4
Reputation: 11259
from copy import deepcopy
d1 = {"admin": {"key1": "v2"}}
d2 = {"admin": {"key2": "v3"},
"user": {"something": "else"}}
def merge(one, two):
if isinstance(two, dict):
result = deepcopy(one)
for key, value in two.iteritems():
if key in result and isinstance(result[key], dict):
result[key] = merge(result[key], value)
else:
result[key] = deepcopy(value)
return result
return two
print merge(d1, d2)
Output
{'admin': {'key2': 'v3', 'key1': 'v2'}, 'user': {'something': 'else'}}
Upvotes: 1
Reputation: 180401
from itertools import chain
from collections import defaultdict
new_d = defaultdict(dict)
for k,v in chain(d1.iteritems(),d2.iteritems()):
new_d[k].update(v)
print(new_d)
defaultdict(<type 'dict'>, {'admin': {'key2': 'v3', 'key1': 'v2'}, 'user': {'something': 'else'}})
Upvotes: 1
Reputation: 362647
If there is only one level of nesting:
>>> d1 = {"admin": {"key1": "v2"}}
>>> d2 = {"admin": {"key2": "v3"},
... "user": {"something": "else"}}
>>> keys = list(d1) + list(d2)
>>> d = {k: dict(d1.get(k, {}).items() + d2.get(k, {}).items()) for k in keys}
>>> d
{'admin': {'key1': 'v2', 'key2': 'v3'}, 'user': {'something': 'else'}}
Deeper nesting will need recursion.
Upvotes: 1