Reputation: 31471
How might one store the path to a value in a dict
of dict
s? For instance, we can easily store the path to the name
value in a variable name_field
:
person = {}
person['name'] = 'Jeff Atwood'
person['address'] = {}
person['address']['street'] = 'Main Street'
person['address']['zip'] = '12345'
person['address']['city'] = 'Miami'
# Get name
name_field = 'name'
print( person[name_field] )
How might the path to the city
value be stored?
# Get city
city_field = ['address', 'city']
print( person[city_field] ) // Obviously won't work!
Upvotes: 3
Views: 905
Reputation: 211982
Here's another way - behaves exactly the same as Simeon Visser's
from operator import itemgetter
pget = lambda map, path: reduce(lambda x,p: itemgetter(p)(x), path, map)
With your example data:
person = {
'name': 'Jeff Atwood',
'address': {
'street': 'Main Street',
'zip': '12345',
'city': 'Miami',
},
}
pget(person, ('address', 'zip')) # Prints '12345'
pget(person, ('name',)) # Prints 'Jeff Atwood'
pget(person, ('nope',)) # Raises KeyError
Upvotes: 1
Reputation:
An alternative that uses Simeon's (and Unubtu's deleted answer) is to create your own dict class that defines an extra method:
class mydict(dict):
def lookup(self, *args):
tmp = self
for field in args:
tmp = tmp[field]
return tmp
person = mydict()
person['name'] = 'Jeff Atwood'
person['address'] = {}
person['address']['street'] = 'Main Street'
person['address']['zip'] = '12345'
person['address']['city'] = 'Miami'
print(person.lookup('address', 'city'))
print(person.lookup('name'))
print(person.lookup('city'))
which results in:
Miami
Jeff Atwood
Traceback (most recent call last):
File "look.py", line 17, in <module>
print(person.lookup('city'))
File "look.py", line 5, in lookup
tmp = tmp[field]
KeyError: 'city'
You can shorten the loop per the suggestion of thefourtheye. If you want to be really fancy, you can probably override private methods like __get__
to allow for a case like person['address', 'city']
, but then things may become tricky.
Upvotes: 1
Reputation: 239463
You can use reduce
function to do this
print reduce(lambda x, y: x[y], city_field, person)
Output
Miami
Upvotes: 4
Reputation: 122346
You can do:
path = ('address', 'city')
lookup = person
for key in path:
lookup = lookup[key]
print lookup
# gives: Miami
This will raise a KeyError
if a part of the path does not exist.
It will also work if path
consists of one value, such as ('name',)
.
Upvotes: 5