I want to generate a list of unique nested keys for each value in a dictionary such that:
input_dict = {"a": {"b": "c", "d": {"e": "f"}}, "f": "g"} expected_result = [["a", "b"], ["a", "d", "e"], ["f"]]
I thought something along these lines would work, appending each key to a list and recursing until a value is reached. At which point I yield a list and carry on.
def _i(itr, list_of_keys): if list_of_keys is None: list_of_keys = [] if isinstance(itr, dict): # For each dict, add the key to the list, and recurse for key, value in itr.items(): list_of_keys.append(key) yield from _i(value, list_of_keys) else: # If not a dict, then at the end of a series of keys, yield the list yield list_of_keys list_of_keys = []
However when running, the result is all the unique keys
x = _i(input_dict, list_of_keys=None) list(x) [['a', 'b', 'd', 'e', 'f'], ['a', 'b', 'd', 'e', 'f'], ['a', 'b', 'd', 'e', 'f']]
Think I must be missing something here on how yielding / input arguments work
Advertisement
Answer
You keep modying the same list object (the reassignment of a local variable at the end there has no effect for any recursive call up or down the stack)! A simpler approach without a carry-over variable would be:
def _i(obj): if isinstance(obj, dict): for k, v in obj.items(): for keys in _i(v): yield [k] + keys else: yield [] >>> list(_i(input_dict)) [['a', 'b'], ['a', 'd', 'e'], ['f']]