如何在嵌套字典中获取每个底层路径的列表(作为键列表)
How to get a list of every bottom level's path (as a list of keys) in a nested dictionary
假设我有这样的字典:
d = {'a': {'values':val}, 'b':{'fin_b': {'values':val}}, 'c':{'ca':{'fin_ca':{'values':val}}, 'cb':{'fin_cb':{'values':val}}}, 'd':{'da':{'dda':{'fin_dda':{'values':val}}}}}
我想创建一个列表,其中包含该项目所有键的每个底层项目的列表。换句话说,嵌套字典中所有项目的所有键的列表列表,而事先不知道字典中有多少层。其中一个警告是它最好忽略每个底层项目中的“值”键。换句话说,d 的正确输出是:
output = [['a'], ['b', 'fin_b'], ['c', 'ca', 'fin_ca'], ['c', 'cb', 'fin_cb'], ['d', 'da', 'dda', 'fin_dda']]
但是:
output = [['a', 'values'], ['b', 'fin_b', 'values'], ['c', 'ca', 'fin_ca', 'values'], ['c', 'cb', 'fin_cb', 'values'], ['d', 'da', 'dda', 'fin_dda', 'values']]
也可以,这是我正在努力解决的检索密钥算法。
我试过以下方法:
def get_paths(self):
data = self.data
groupings = []
group = []
def convert(d):
nonlocal group
for k in d.keys():
if isinstance(d[k], dict) :
group.append(k)
yield from (x for x in convert(d[k]))
else:
group_ = group.copy()
group = []
yield group_
for item in convert(data):
groupings.append(item)
return groupings
但我得到:
output = [['a'], ['b', 'fin_b'], ['c', 'ca', 'fin_ca'], ['cb', 'fin_cb'], ['d', 'da', 'dda', 'fin_dda']]
由于重置了最后一级的列表“组”。我也试过:
def get_paths(self):
data = self.data
groupings = []
group = []
def convert(d):
for k in d.keys():
if isinstance(d[k], dict) and 'values' not in v.keys():
yield from ([k,x] for x in convert(d[k]))
elif 'values' in d.keys():
yield k
for item in convert(data):
groupings.append(item)
return groupings
但问题是它 returns 一个嵌套列表,我无法绕过它:
output = ['a', ['b', 'fin_b'], ['c', ['ca', 'fin_ca']], ['c', ['cb', 'fin_cb']], ['d', ['da', ['dda', 'fin_dda']]]]
如有任何建议,我们将不胜感激。
这给出了所需的输出:
def get_paths(dictionary, current_path=None, paths_found=None):
if current_path is None:
current_path = []
if paths_found is None:
paths_found = []
for key, value in dictionary.items():
if isinstance(value, dict):
get_paths(value, current_path + [key], paths_found)
else:
if current_path:
paths_found.append(current_path)
return paths_found
if __name__ == "__main__":
d = {'a': {'values': "val"}, 'b': {'fin_b': {'values': "val"}},
'c': {'ca': {'fin_ca': {'values': "val"}}, 'cb': {'fin_cb': {'values': "val"}}},
'd': {'da': {'dda': {'fin_dda': {'values': "val"}}}}}
print(get_paths(d))
您可以通过两步解决方案解决此问题:
- 在这种情况下,您可以检索包括叶节点在内的完整路径
{"values": val}
- 可以过滤掉叶节点
我们可以使用迭代器:
要解决第一个问题,递归迭代器就足够了:
def iter_path(dict_in, prefix=None):
if prefix is None:
prefix = list()
for key, value in dict_in.items():
if not isinstance(value, dict):
yield prefix + [key]
else:
yield from iter_path(value, prefix + [key])
对于第二点,我们可以删除生成列表的最后一个条目:
def iter_path_not_last(dict_in):
for path in iter_path(dict_in, prefix=None):
yield p[:-1]
终于
paths = [p for p in iter_path_not_last(d)]
假设我有这样的字典:
d = {'a': {'values':val}, 'b':{'fin_b': {'values':val}}, 'c':{'ca':{'fin_ca':{'values':val}}, 'cb':{'fin_cb':{'values':val}}}, 'd':{'da':{'dda':{'fin_dda':{'values':val}}}}}
我想创建一个列表,其中包含该项目所有键的每个底层项目的列表。换句话说,嵌套字典中所有项目的所有键的列表列表,而事先不知道字典中有多少层。其中一个警告是它最好忽略每个底层项目中的“值”键。换句话说,d 的正确输出是:
output = [['a'], ['b', 'fin_b'], ['c', 'ca', 'fin_ca'], ['c', 'cb', 'fin_cb'], ['d', 'da', 'dda', 'fin_dda']]
但是:
output = [['a', 'values'], ['b', 'fin_b', 'values'], ['c', 'ca', 'fin_ca', 'values'], ['c', 'cb', 'fin_cb', 'values'], ['d', 'da', 'dda', 'fin_dda', 'values']]
也可以,这是我正在努力解决的检索密钥算法。
我试过以下方法:
def get_paths(self):
data = self.data
groupings = []
group = []
def convert(d):
nonlocal group
for k in d.keys():
if isinstance(d[k], dict) :
group.append(k)
yield from (x for x in convert(d[k]))
else:
group_ = group.copy()
group = []
yield group_
for item in convert(data):
groupings.append(item)
return groupings
但我得到:
output = [['a'], ['b', 'fin_b'], ['c', 'ca', 'fin_ca'], ['cb', 'fin_cb'], ['d', 'da', 'dda', 'fin_dda']]
由于重置了最后一级的列表“组”。我也试过:
def get_paths(self):
data = self.data
groupings = []
group = []
def convert(d):
for k in d.keys():
if isinstance(d[k], dict) and 'values' not in v.keys():
yield from ([k,x] for x in convert(d[k]))
elif 'values' in d.keys():
yield k
for item in convert(data):
groupings.append(item)
return groupings
但问题是它 returns 一个嵌套列表,我无法绕过它:
output = ['a', ['b', 'fin_b'], ['c', ['ca', 'fin_ca']], ['c', ['cb', 'fin_cb']], ['d', ['da', ['dda', 'fin_dda']]]]
如有任何建议,我们将不胜感激。
这给出了所需的输出:
def get_paths(dictionary, current_path=None, paths_found=None):
if current_path is None:
current_path = []
if paths_found is None:
paths_found = []
for key, value in dictionary.items():
if isinstance(value, dict):
get_paths(value, current_path + [key], paths_found)
else:
if current_path:
paths_found.append(current_path)
return paths_found
if __name__ == "__main__":
d = {'a': {'values': "val"}, 'b': {'fin_b': {'values': "val"}},
'c': {'ca': {'fin_ca': {'values': "val"}}, 'cb': {'fin_cb': {'values': "val"}}},
'd': {'da': {'dda': {'fin_dda': {'values': "val"}}}}}
print(get_paths(d))
您可以通过两步解决方案解决此问题:
- 在这种情况下,您可以检索包括叶节点在内的完整路径
{"values": val}
- 可以过滤掉叶节点
我们可以使用迭代器:
要解决第一个问题,递归迭代器就足够了:
def iter_path(dict_in, prefix=None):
if prefix is None:
prefix = list()
for key, value in dict_in.items():
if not isinstance(value, dict):
yield prefix + [key]
else:
yield from iter_path(value, prefix + [key])
对于第二点,我们可以删除生成列表的最后一个条目:
def iter_path_not_last(dict_in):
for path in iter_path(dict_in, prefix=None):
yield p[:-1]
终于
paths = [p for p in iter_path_not_last(d)]