I have a dictionary in the following format:
data = {
'Bob': {
'age': 12,
'weight': 150,
'eye_color': 'blue'
},
'Jim': {
'favorite_food': 'cherries',
'sport': 'baseball',
'hobby': 'running'
},
'Tom': {
'strength': 'average',
'endurance': 'high',
'heart_rate': 'low'
}
}
What is the most Pythonic way to concatenate all of the dictionaries within dict into a new dictionary so that I would end up with something like the following:
new_dict = {
'age': 12,
'weight': 150,
'eye_color': 'blue',
'favorite_food': 'cherries',
'sport': 'baseball',
'hobby': 'running',
'strength': 'average',
'endurance': 'high',
'heart_rate': 'low'
}
CodePudding user response:
You can use functools.reduce()
to build up the result, unioning one dictionary at a time:
from functools import reduce
data = {
'Bob' : { 'age': 12, 'weight': 150, 'eye_color': 'blue' },
'Jim' : { 'favorite_food': 'cherries', 'sport': 'baseball', 'hobby': 'running' },
'Tom' : { 'strength': 'average', 'endurance': 'high', 'hear_rate': 'low' }
}
result = reduce(lambda x, y: dict(**x, **y), data.values(), {})
print(result)
This outputs:
{'age': 12, 'weight': 150, 'eye_color': 'blue', 'favorite_food': 'cherries',
'sport': 'baseball', 'hobby': 'running', 'strength': 'average',
'endurance': 'high', 'hear_rate': 'low'}
On Python 3.9 or higher, you can use lambda x: x | y
, operator.or_
, or dict.__or__
instead of lambda x: dict(**x, **y)
if you're on Python 3.9 or higher. The latter two are from a suggestion by Mad Physicist.
CodePudding user response:
One option is to use a dictionary comprehension with a nested generator expression:
new_dict = {k: v for d in data.values() for k, v in d.items()}
Another way that's subtly different to to use collections.ChainMap
:
new_dict = collections. ChainMap(*data.values())
In this case, new_dict
will not be a dict
, but will quack like one just fine. Lookup will be a bit slower, but construction will be faster.