如何根据其他键更新Python defaultdict中的值
问题描述
我们有一个类似defaultdict(list)结构的列表数据:
l = [('S', ['(', 'Num']), ('Num',['Sign', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']), ('Op', ['+', '-', '*', '/']), ('Sign', ['-'])]
需要实现多层递归替换:遍历每个键对应的列表,若列表中的元素是集合中的其他键名,则将该元素替换为对应键的取值列表内容,最终得到完全展开的结果:
最终结果: [('S', ['(', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']), ('Num',['-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']), ('Op', ['+', '-', '*', '/']), ('Sign', ['-'])]
解决方案
这里的核心是循环检查并替换所有可展开的键,直到没有可以替换的元素为止。具体实现步骤如下:
- 先将原始列表转换为字典,方便快速查找键对应的取值列表
- 对每个键的列表进行循环替换,直到列表中没有任何元素是字典的键
- 最后将处理后的字典转换回原始的列表格式
以下是完整的Python代码:
# 原始数据 l = [('S', ['(', 'Num']), ('Num',['Sign', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']), ('Op', ['+', '-', '*', '/']), ('Sign', ['-'])] # 步骤1:转换为字典,方便快速查找 rule_dict = dict(l) # 步骤2:定义替换函数,循环处理直到没有可替换的键 def expand_list(target_list, lookup_dict): changed = True while changed: changed = False new_list = [] for item in target_list: if item in lookup_dict: # 如果当前元素是键,替换为对应的列表元素 new_list.extend(lookup_dict[item]) changed = True else: new_list.append(item) target_list = new_list return target_list # 步骤3:遍历所有键,处理对应的列表 expanded_dict = {} for key, value in rule_dict.items(): expanded_dict[key] = expand_list(value.copy(), rule_dict) # 步骤4:转换回原始的列表格式 l_new = list(expanded_dict.items()) # 打印结果 print(l_new)
代码解释
- 字典转换:把列表转成字典
rule_dict,这样我们可以用O(1)的时间复杂度快速判断某个元素是否是需要替换的键,提升效率。 - 循环替换:
expand_list函数里用while循环持续检查列表元素,只要有元素被替换,就继续循环——这能保证多层嵌套的键也会被完全展开(比如示例中S里的Num先替换为Sign+数字,接着Sign再替换为-)。 - 列表扩展:用
extend把对应列表的元素逐个添加进去,避免出现嵌套列表的情况,保证最终结果的格式符合预期。 - 格式还原:处理完所有键后,把字典转回
(键, 列表)的元组列表格式,和原始数据结构保持一致。
运行这段代码后,就能得到你预期的完全展开的结果啦。
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

