简体   繁体   中英

Get all parents keys in nested dictionary for all items

I want to get all parent keys for all items in a nested python dictionary with unlimited levels. Take an analogy, if you think of a nested dictionary as a directory containing sub-directories, the behaviour I want is similar to what glob.glob(dir, recursive=True) does.

For example, suppose we have the following dictionary:

sample_dict = {
  "key_1": {
    "sub_key_1": 1,
    "sub_key_2": 2,
  },
  "key_2": {
    "sub_key_1": 3,
    "sub_key_2": {
      "sub_sub_key_1": 4,
    },
  },
}

I want to get the full "path" of every value in the dictionary:

["key_1", "sub_key_1", 1]
["key_1", "sub_key_2", 2]
["key_2", "sub_key_1", 3]
["key_2", "sub_key_2", "sub_sub_key_1", 4]

Just wondering if there is a clean way to do that?

Using generators can often simplify the code for these type of tasks and make them much more readable while avoiding passing explicit state arguments to the function. You get a generator instead of a list, but this is a good thing because you can evaluate lazily if you want to. For example:

def getpaths(d):
    if not isinstance(d, dict):
        yield [d]
    else:
        yield from ([k] + w for k, v in d.items() for w in getpaths(v))

result = list(getpaths(sample_dict))

Result will be:

[['key_1', 'sub_key_1', 1],
 ['key_1', 'sub_key_2', 2],
 ['key_2', 'sub_key_1', 3],
 ['key_2', 'sub_key_2', 'sub_sub_key_1', 4]]

You can solve it recursively

sample_dict = {
  "key_1": {
    "sub_key_1": 1,
    "sub_key_2": 2,
  },
  "key_2": {
    "sub_key_1": 3,
    "sub_key_2": {
      "sub_sub_key_1": 4,
    },
  }
}

def full_paths(sample_dict, paths=[], parent_keys=[]):
    for key in sample_dict.keys():
        if type(sample_dict[key]) is dict:
            full_paths(sample_dict[key], paths=paths, parent_keys=(parent_keys + [key]))
        else:
            paths.append(parent_keys + [key] + [sample_dict[key]])
    return paths

print(full_paths(sample_dict))

You can use this solution.

sample_dict = {
  "key_1": {
    "sub_key_1": 1,
    "sub_key_2": 2,
  },
  "key_2": {
    "sub_key_1": 3,
    "sub_key_2": {
      "sub_sub_key_1": 4,
    },
  },
}

def key_find(sample_dict, li=[]):
    for key, val in sample_dict.items():
        if isinstance(val, dict):
            key_find(val, li=li + [key])
        else:
            print(li + [key] + [val])

key_find(sample_dict)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM