假设我有一个以下形式的嵌套字典:
{'geo': {'bgcolor': 'white','lakecolor': 'white','caxis': {'gridcolor': 'white', 'linecolor': 'white',}},
'title': {'x': 0.05},
'yaxis': {'automargin': True,'linecolor': 'white','zerolinecolor': 'white','zerolinewidth': 2}
}
Run Code Online (Sandbox Code Playgroud)
您如何通过该 dict 工作并列出包含该值的每个完整键路径'white'
?使用用户 jfs 在帖子中定义的函数在嵌套字典中搜索值 python可以检查是否'white'
至少出现一次并返回路径:
# dictionary
d={'geo': {'bgcolor': 'white','lakecolor': 'white','caxis': {'gridcolor': 'white', 'linecolor': 'white',}},
'title': {'x': 0.05},
'yaxis': {'automargin': True,'linecolor': 'white','ticks': '','zerolinecolor': 'white','zerolinewidth': 2}
}
# function:
def getpath(nested_dict, value, prepath=()):
for k, v in nested_dict.items():
path = prepath + (k,)
if v == value: # found value
return path
elif hasattr(v, 'items'): # v is a dict
p = getpath(v, value, path) # recursive call
if p is not None:
return p
getpath(d,'white')
# out:
('geo', 'bgcolor')
Run Code Online (Sandbox Code Playgroud)
但是“白色”也出现在其他地方,例如:
1. d['geo']['lakecolor']
2: d['geo']['caxis']['gridcolor']
3: d['yaxis']['linecolor']
如何确保该函数找到所有路径?
我已经尝试应用上面的函数直到它返回,none
同时逐个消除找到的路径,但这很快就变成了一个丑陋的烂摊子。
感谢您的任何建议!
这是编写生成器的完美用例:
def find_paths(haystack, needle):
if haystack == needle:
yield ()
if not isinstance(haystack, dict):
return
for key, val in haystack.items():
for subpath in find_paths(val, needle):
yield (key, *subpath)
Run Code Online (Sandbox Code Playgroud)
您可以按如下方式使用它:
d = {
'geo': {'bgcolor': 'white','lakecolor': 'white','caxis': {'gridcolor': 'white', 'linecolor': 'white',}},
'title': {'x': 0.05},
'yaxis': {'automargin': True,'linecolor': 'white','ticks': '','zerolinecolor': 'white','zerolinewidth': 2}
}
# you can iterate over the paths directly...
for path in find_paths(d, 'white'):
print('found at path: ', path)
# ...or you can collect them into a list:
paths = list(find_paths(d, 'white'))
print('found at paths: ' + repr(paths))
Run Code Online (Sandbox Code Playgroud)
生成器方法的优点是不需要创建一个对象来一次将所有路径保存在内存中;它们可以一一处理并立即丢弃。在这种情况下,内存节省会相当适中,但在其他情况下,它们可能很重要。此外,如果迭代生成器的循环提前终止,生成器将不会继续搜索更多的路径,这些路径无论如何都会被丢弃。