Accessing value inside nested dictionaries

Question:

I am new to python and need help in solving an issue:

I have a dictionary like

tmpDict = {'ONE':{'TWO':{'THREE':10}}}

Do we have any other way to access THREE’s value other than doing

tmpDict['ONE']['TWO']['THREE']

?

Asked By: Gana

||

Answers:

No, those are nested dictionaries, so that is the only real way (you could use get() but it’s the same thing in essence). However, there is an alternative. Instead of having nested dictionaries, you can use a tuple as a key instead:

tempDict = {("ONE", "TWO", "THREE"): 10}
tempDict["ONE", "TWO", "THREE"]

This does have a disadvantage, there is no (easy and fast) way of getting all of the elements of "TWO" for example, but if that doesn’t matter, this could be a good solution.

Answered By: Gareth Latty

You can use the get() on each dict. Make sure that you have added the None check for each access.

As always in python, there are of course several ways to do it, but there is one obvious way to do it.

tmpdict["ONE"]["TWO"]["THREE"] is the obvious way to do it.

When that does not fit well with your algorithm, that may be a hint that your structure is not the best for the problem.

If you just want to just save you repetative typing, you can of course alias a subset of the dict:

>>> two_dict = tmpdict['ONE']['TWO'] # now you can just write two_dict for tmpdict['ONE']['TWO']
>>> two_dict["spam"] = 23
>>> tmpdict
{'ONE': {'TWO': {'THREE': 10, 'spam': 23}}}
Answered By: ch3ka

My implementation:

def get_nested(data, *args):
    if args and data:
        element  = args[0]
        if element:
            value = data.get(element)
            return value if len(args) == 1 else get_nested(value, *args[1:])

Example usage:

>>> dct={"foo":{"bar":{"one":1, "two":2}, "misc":[1,2,3]}, "foo2":123}
>>> get_nested(dct, "foo", "bar", "one")
1
>>> get_nested(dct, "foo", "bar", "two")
2
>>> get_nested(dct, "foo", "misc")
[1, 2, 3]
>>> get_nested(dct, "foo", "missing")
>>>

There are no exceptions raised in case a key is missing, None value is returned in that case.

Answered By: grafi71

The answer was given already by either Sivasubramaniam Arunachalam or ch3ka.

I am just adding a performances view of the answer.

dicttest={}
dicttest['ligne1']={'ligne1.1':'test','ligne1.2':'test8'}
%timeit dicttest['ligne1']['ligne1.1']
%timeit dicttest.get('ligne1').get('ligne1.1')

gives us :

112 ns ± 29.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

235 ns ± 9.82 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Answered By: Mayeul sgc
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.