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?

Asked By: aberger

||

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"))
Answered By: Kevin

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)

Answered By: Bahrom

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
Answered By: jar

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.

Answered By: Vamsi
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.