I want to generate a list of unique nested keys for each value in a dictionary such that:
JavaScript
x
4
1
input_dict = {"a": {"b": "c", "d": {"e": "f"}}, "f": "g"}
2
3
expected_result = [["a", "b"], ["a", "d", "e"], ["f"]]
4
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.
JavaScript
1
14
14
1
def _i(itr, list_of_keys):
2
if list_of_keys is None:
3
list_of_keys = []
4
5
if isinstance(itr, dict):
6
# For each dict, add the key to the list, and recurse
7
for key, value in itr.items():
8
list_of_keys.append(key)
9
yield from _i(value, list_of_keys)
10
else:
11
# If not a dict, then at the end of a series of keys, yield the list
12
yield list_of_keys
13
list_of_keys = []
14
However when running, the result is all the unique keys
JavaScript
1
7
1
x = _i(input_dict, list_of_keys=None)
2
list(x)
3
4
[['a', 'b', 'd', 'e', 'f'],
5
['a', 'b', 'd', 'e', 'f'],
6
['a', 'b', 'd', 'e', 'f']]
7
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:
JavaScript
1
11
11
1
def _i(obj):
2
if isinstance(obj, dict):
3
for k, v in obj.items():
4
for keys in _i(v):
5
yield [k] + keys
6
else:
7
yield []
8
9
>>> list(_i(input_dict))
10
[['a', 'b'], ['a', 'd', 'e'], ['f']]
11