Python递归遍历字典:记录嵌套层级并保留重复键方法问询
我来帮你搞定这个问题,你的需求可以拆成两个核心点:记录每个键的嵌套层级,以及让重复键(比如嵌套里的"12")能被纳入列表而不被忽略。下面是具体的思路和修改后的代码:
核心思路
原来的代码只存储键本身,导致重复键会被if key not in keys_list过滤掉。我们需要给每个键加上唯一标识,最直观的就是它的嵌套层级,或者完整的嵌套路径——这样即使键名相同,只要层级/路径不同,就会被视为不同的元素,自然不会被忽略。同时,我们可以通过给递归函数添加参数来追踪当前的嵌套层级。
方案1:存储「键+层级」的元组(推荐)
这种方式既保留了键的原始名称,又明确记录了它的嵌套层级,实现起来也很简单:
d = {"12": "a", "3": "b", "8": { "12": "c", "25": "d" } } def iterate_with_depth(dictionary, depth=1): keys_info = [] for key, value in dictionary.items(): # 把键和当前层级打包成元组存入列表 keys_info.append((key, depth)) # 如果当前值是字典,递归调用并合并结果 if isinstance(value, dict): keys_info.extend(iterate_with_depth(value, depth + 1)) return keys_info # 调用函数获取结果 result = iterate_with_depth(d) print(result) # 输出结果:[('12', 1), ('3', 1), ('8', 1), ('12', 2), ('25', 2)]
这里的depth参数初始为1(表示顶层键的层级),每次递归进入子字典时层级加1。返回的列表里每个元素是元组,第一个元素是键名,第二个是嵌套层级,完美解决了重复键的问题——嵌套的"12"因为层级是2,和顶层的"12"(层级1)是不同的元组,所以不会被过滤。
方案2:存储带层级标识的字符串
如果你希望结果是纯字符串形式,可以把键和层级拼接成唯一的字符串:
def iterate_with_named_key(dictionary, depth=1): keys_info = [] for key, value in dictionary.items(): # 格式化为类似 "12_1" 的字符串,后缀是层级 keys_info.append(f"{key}_{depth}") if isinstance(value, dict): keys_info.extend(iterate_with_named_key(value, depth + 1)) return keys_info result = iterate_with_named_key(d) print(result) # 输出结果:['12_1', '3_1', '8_1', '12_2', '25_2']
方案3:存储完整嵌套路径(更直观)
如果需要更清晰地知道每个键的具体位置,可以存储从根到当前键的完整路径:
def iterate_with_path(dictionary, current_path=None): if current_path is None: current_path = [] keys_info = [] for key, value in dictionary.items(): # 生成当前键的完整路径 new_path = current_path + [key] keys_info.append(new_path) if isinstance(value, dict): keys_info.extend(iterate_with_path(value, new_path)) return keys_info result = iterate_with_path(d) print(result) # 输出结果:[['12'], ['3'], ['8'], ['8', '12'], ['8', '25']]
这种方式能一眼看出每个键的嵌套位置,比如['8', '12']就表示它是顶层键"8"下面的子键"12",非常直观。
关于原代码的小优化
原代码依赖全局的keys_list,其实更推荐让函数直接返回结果列表,这样代码更模块化,也避免了全局变量带来的潜在问题。如果一定要保留全局变量的写法,也可以修改存储内容为元组或字符串,比如:
d = {"12": "a", "3": "b", "8": { "12": "c", "25": "d" } } keys_list = [] def iterate(dictionary, depth=1): for key, value in dictionary.items(): key_with_depth = (key, depth) # 现在判断的是元组是否存在,而不是单独的键 if key_with_depth not in keys_list: keys_list.append(key_with_depth) if isinstance(value, dict): iterate(value, depth + 1) iterate(d) print(keys_list) # 输出:[('12', 1), ('3', 1), ('8', 1), ('12', 2), ('25', 2)]
另外,因为Python字典的键本身是唯一的,同一个字典里不会出现重复键,所以其实可以去掉if key_with_depth not in keys_list这个判断,直接append,这样效率更高。
内容的提问来源于stack exchange,提问作者codingInMyBasement

