Python 2:如何在含嵌套字典与列表的结构中查找某个键的所有值
Python 2:如何在含嵌套字典与列表的结构中查找某个键的所有值
我完全懂你的困扰!你现在的递归函数一找到目标键的匹配项就直接返回了,导致只能拿到最高层级的结果,没法把所有嵌套层级里的目标键值都收集起来,而且尝试用yield的时候卡壳了对吧?别慌,咱们来一步步解决这个问题。
首先分析下你原函数的问题:每次找到匹配或者递归得到结果就立刻return,这会直接终止后续的遍历,自然没法收集到所有层级的匹配项。我们需要的是遍历整个嵌套结构,只要遇到目标键就记录它的值,同时继续递归遍历嵌套的内容,把所有符合条件的结果都捞出来。
接下来给你两个方案,一个是用你尝试过的yield生成器(更灵活,适合大结构),另一个是用列表收集结果(更直观)。
方案一:使用yield生成器(推荐)
这个方案用生成器逐个返回找到的匹配值,不会一次性占用太多内存,适合处理大的嵌套结构:
def search_dict_list(collection, desired_key): """ 递归查找嵌套字典/列表中所有层级的desired_key对应的value :param collection: 待搜索的嵌套结构(dict或list) :param desired_key: 要查找的目标键 :yield: 每个匹配到的value """ if isinstance(collection, dict): # 先检查当前字典是否包含目标键,有的话返回对应的值 if desired_key in collection: yield collection[desired_key] # 递归遍历这个值本身,看看里面有没有嵌套的目标键 for result in search_dict_list(collection[desired_key], desired_key): yield result # 遍历当前字典的所有值,继续递归搜索 for value in collection.values(): for result in search_dict_list(value, desired_key): yield result elif isinstance(collection, list): # 遍历列表中的每个元素,递归搜索 for item in collection: for result in search_dict_list(item, desired_key): yield result
怎么使用这个函数?
如果你想把所有结果收集到一个列表里,直接用list()包裹调用即可:
test_dict = { "mock_key_1": [ { "mock_key_2": [ { "mock_key_3": { "mock_key_4": { "mock_key_5": [ {"target_key": "target_value_1"}, {"target_key": "target_value_2"}, ], }, "mock_key_6": { "mock_key_7": "mock_value_7", "mock_key_8": "mock_value_8", "mock_key_9": "mock_value_9", }, "target_key": ["target_value_3"], } } ], "target_key": {"mock_key_10" : "target_value_4"}, } ] } # 收集所有匹配结果 results = list(search_dict_list(test_dict, "target_key")) print(results)
运行后得到的结果正好符合你的预期:
[{"mock_key_10": "target_value_4"}, ["target_value_3"], "target_value_1", "target_value_2"]
方案二:用列表收集结果
如果你觉得生成器有点绕,也可以用一个列表来收集所有结果,这种方式更直观:
def search_dict_list(collection, desired_key, results=None): """ 递归查找嵌套字典/列表中所有层级的desired_key对应的value,存入results列表 :param collection: 待搜索的嵌套结构(dict或list) :param desired_key: 要查找的目标键 :param results: 用于收集结果的列表,无需手动传入 :return: 包含所有匹配值的列表 """ if results is None: results = [] if isinstance(collection, dict): if desired_key in collection: results.append(collection[desired_key]) # 递归遍历当前值,继续查找嵌套的目标键 search_dict_list(collection[desired_key], desired_key, results) # 遍历所有值递归搜索 for value in collection.values(): search_dict_list(value, desired_key, results) elif isinstance(collection, list): for item in collection: search_dict_list(item, desired_key, results) return results
使用方式:
results = search_dict_list(test_dict, "target_key") print(results)
同样会得到你想要的结果。
为什么这个解决方案能行?
- 我们没有在找到第一个匹配项就终止,而是继续遍历整个结构的每一个角落
- 当找到目标键时,不仅记录当前值,还会递归遍历这个值本身,确保不会漏掉嵌套在值里面的目标键
- 生成器版本可以按需获取结果,列表版本则直接返回所有结果,按需选择就好
备注:内容来源于stack exchange,提问作者A.Martinez
相关产品推荐
相关产品推荐

