pythonic way to get the values from each of the last level of nested dictionary

Viewed 91

I have the following dict:

x = {'NIH': {'slide_1': {'ROI1': [1], 'ROI2': [2]}}}

And I want to get the last nested level dict, I'm currently doing the following:

x = list(list(list(cc.values())[0].values())[0])

I was wondering if there is a more elegant way of achieving the same results. There are more levels to the nested dict but for the sake of the question this example should suffice.

4 Answers

This is a generic way of getting the last nested level dict even for variable levels of nesting:

        x = {'NIH': {'slide_1': {'ROI1': [1], 'ROI2': [2]}}}      
        while isinstance(y := list(x.values())[0], dict):
            x = y
        print(x)

Output:

{'ROI1': [1], 'ROI2': [2]}

I am not sure if there is a pythonic way, but you can use a recursive function:

cc = {'NIH': {'slide_1': {'ROI1': [1], 'ROI2': [2]}}}

def getLatestLevel(dictionary, values=[]):
    for key, item in dictionary.items():
        if type(item) is dict:
            values = getLatestLevel(item, values)
        else:
            values.append(key)
    return values
            
x = getLatestLevel(cc)

Output of print(x):

['ROI1', 'ROI2']

It returns the same as your proposed line but is general. Replace key by item if you want to get the values instead of the keys.

Note: This will collect all the entries from each of the last levels (leafs) of the dictionary tree even if some nested dictionaries which are not the leafs contain multiple entries. If dictionaries along the path are known to only contain one entry, then @constantstranger solution is certainly simpler.

I'm not quite sure in this code. But anyway it works with given example. You can test this with your data:

import pandas as pd

x = {'NIH': {'slide_1': {'ROI1': [1], 'ROI2': [2]}}}

res = pd.json_normalize(x).rename(lambda x: x.split('.')[-1], axis=1).T.to_dict()[0]
'''
{'ROI1': [1], 'ROI2': [2]}

You could give ndicts a go

pip install ndicts

Then import NestedDict in your script and initialize one

from ndicts.ndicts import NestedDict

x = {'NIH': {'slide_1': {'ROI1': [1], 'ROI2': [2]}}}
nd = NestedDict(x)

It's not clear from your question if you want the leaf values, the leaf keys or both combined in a dictionary, so here you have how to obtain all of them

>>> # Values
>>> list(nd.values())
    [[1], [2]]
>>> # Keys
>>> [key[-1] for key in nd]
    ["ROI1", "ROI2"]
>>> # Dictionary
>>> {key[-1]: value for key, value in nd.items()}
    {"ROI1": [1], "ROI2": [2]}
Related