Pass nested dictionary location as parameter in Python
Question:
If I have a nested dictionary I can get a key by indexing like so:
>>> d = {'a':{'b':'c'}}
>>> d['a']['b']
'c'
Am I able to pass that indexing as a function parameter?
def get_nested_value(d, path=['a']['b']):
return d[path]
Obviously, this is incorrect, I get TypeError: list indices must be integers, not str
.
How can I do it correctly?
Answers:
By rewriting your function body a little bit, you can pass the keys as a tuple or other sequence:
def get_nested_value(d, keys):
for k in keys:
d = d[k]
return d
d = {'a':{'b':'c'}}
print get_nested_value(d, ("a", "b"))
You can use reduce
(or functools.reduce
in python 3), but that would also require you to pass in a list/tuple of your keys:
>>> def get_nested_value(d, path=('a', 'b')):
return reduce(dict.get, path, d)
>>> d = {'a': {'b': 'c'}}
>>> get_nested_value(d)
'c'
>>>
(In your case ['a']['b']
doesn’t work because ['a']
is a list, and ['a']['b']
is trying to look up the element at “b“th index of that list)
You can solve it with a recursive function:
def access_path (lambda json, path):
if len(path) == 0:
return json
else
return access_path(json[path[0]], path[1:]))
This works for both a nested dict-of-dicts, and a list of dicts:
test = {
'a' : {
'b' : 420
},
'c' : [
{
'id' : 'd1'
},
{
'id' : 'd2'
},
{
'id' : 'd3'
},
]
}
print(access_path(test, ['a', 'b']))
print(access_path(test, ['c', 1, 'id']))
prints
420
d2
Take a look at https://github.com/akesterson/dpath-python.
It makes traversing nested dictionaries a lot easier.
It will iterate out all of the conditions in the dictionary, so no special looping constructs required.
If I have a nested dictionary I can get a key by indexing like so:
>>> d = {'a':{'b':'c'}}
>>> d['a']['b']
'c'
Am I able to pass that indexing as a function parameter?
def get_nested_value(d, path=['a']['b']):
return d[path]
Obviously, this is incorrect, I get TypeError: list indices must be integers, not str
.
How can I do it correctly?
By rewriting your function body a little bit, you can pass the keys as a tuple or other sequence:
def get_nested_value(d, keys):
for k in keys:
d = d[k]
return d
d = {'a':{'b':'c'}}
print get_nested_value(d, ("a", "b"))
You can use reduce
(or functools.reduce
in python 3), but that would also require you to pass in a list/tuple of your keys:
>>> def get_nested_value(d, path=('a', 'b')):
return reduce(dict.get, path, d)
>>> d = {'a': {'b': 'c'}}
>>> get_nested_value(d)
'c'
>>>
(In your case ['a']['b']
doesn’t work because ['a']
is a list, and ['a']['b']
is trying to look up the element at “b“th index of that list)
You can solve it with a recursive function:
def access_path (lambda json, path):
if len(path) == 0:
return json
else
return access_path(json[path[0]], path[1:]))
This works for both a nested dict-of-dicts, and a list of dicts:
test = {
'a' : {
'b' : 420
},
'c' : [
{
'id' : 'd1'
},
{
'id' : 'd2'
},
{
'id' : 'd3'
},
]
}
print(access_path(test, ['a', 'b']))
print(access_path(test, ['c', 1, 'id']))
prints
420
d2
Take a look at https://github.com/akesterson/dpath-python.
It makes traversing nested dictionaries a lot easier.
It will iterate out all of the conditions in the dictionary, so no special looping constructs required.