Reputation: 67
I have two nested dicts with same master keys:
dict1 = {'person1': {'name': 'John', 'sex': 'Male'},
'person2': {'name': 'Marie', 'sex': 'Female'},
'person3': {'name': 'Luna', 'sex': 'Female'},
'person4': {'name': 'Peter', 'sex': 'Male'}}
dict2 = {'person1': {'weight': '81.1', 'age': '27'},
'person2': {'weight': '56.7', 'age': '22'},
'person3': {'weight': '63.4', 'age': '24'},
'person4': {'weight': '79.1', 'age': '29'}}
So I want to enrich dict 1 by the key value pairs from dict2.
I'm able to do so with a for loop...
for key in dict2:
dict2[key]['age'] = dict1[key]['age']
dict2[key]['weight'] = dict2[key]['weight']
Result:
dict2 = {'person1': {'name': 'John', 'sex': 'Male', 'weight': '81.1', 'age': '27'},
'person2': {'name': 'Marie', 'sex': 'Female', 'weight': '56.7', 'age': '22'},
'person3': {'name': 'Luna', 'sex': 'Female', 'weight': '63.4', 'age': '24'},
'person4': {'name': 'Peter', 'sex': 'Male', 'weight': '79.1', 'age': '29'}}
...but is there a more pythonic way to do so - e.g. with dict comprehension?
Upvotes: 1
Views: 2800
Reputation: 65
The answers do not consider levels deeper than 2 in the dicts to be merged, to merge to any depth use the following recursion:
def merge_nested_dicts(dict1, dict2):
res = {}
for key, value in dict1.items():
if key in dict2:
res[key] = merge_nested_dicts(dict1[key], dict2[key])
del dict2[key]
else:
res[key]=value
res.update(dict2)
return res
Upvotes: 0
Reputation: 1459
If you have control over the data source flatten the dictionaries and then use the update
method. For example:
dict1 = {('person1', 'name'): 'John'}
dict2 = {('person1', 'weight'): 81.1}
dict1.update(dict2)
>>> dict1
{('person1', 'name'): 'John',
('person1', 'weight'): 81.1}
It is much easier to deal with this kind of data structure, but if you are stuck with nested dictionaries you can use a NestedDict
to achieve the same result with a similar interface.
from ndicts import NestedDict
nd1 = NestedDict(dict1)
nd2 = NestedDict(dict2)
nd1.update(nd2)
>>> nd1
NestedDict(
{'person1': {'name': 'John', 'weight': 81.1}}
)
Use nd1.to_dict()
if you need the result as a dictionary.
To install ndicts pip install ndicts
.
Upvotes: 0
Reputation: 790
Yes:
dict3 = {k: {**v, **dict2[k]} for k, v in dict1.items()}
Firstly, use .items()
to iterate over both keys and values at the same time.
Then, for each key k
you want the value to be a new dict that is created by dumping — or destructuring — both v
and dict2[k]
in it.
UPDATE for Python >= 3.9:
Thanks @mwo for mentioning the pipe |
operand:
dict3 = {k: v | dict2[k] for k, v in dict1.items()}
Upvotes: 3