Search code examples
pythondictionaryrecursion

Dynamically get a list of keys to access the deepest non-dict values in a nest dictionary


I have a dictionary where I want to return a dynamic list of the keys that would access any non-dict values. I do not know the structure of the dictionary beforehand and nesting could go n-levels.

{
    "parent": {
        "a": 1,
        "b": {
            "nested": "first"
        }
    }
}

From this dictionary, I want to return the following list of lists:

[
    ["parent", "a"],
    ["parent", "b", "nested"]
]

I plan to use this list with functools and reduce to get specific values out of the dictionary to build a new dictionary. I've tried a recursion function to lop through the dictionary items and check for isinstance(value, dict), but I'm having issues keeping the path together. Any help is much appreciated, thanks!


Solution

  • You can add the paths of the sub-dicts generated from recursive calls with the dict values to the keys of the current dict. Since you don't need leaf values, yield an empty list for them:

    def paths(d):
        if isinstance(d, dict):
            yield from ([k, *p] for k, v in d.items() for p in paths(v))
        else:
            yield []
    

    so that:

    d = {
        "parent": {
            "a": 1,
            "b": {
                "nested": "first"
            }
        }
    }
    print(list(paths(d)))
    

    outputs:

    [['parent', 'a'], ['parent', 'b', 'nested']]
    

    Demo: https://ideone.com/Q5I8lK