如何将多层Python字典展开为字典列表?
问题描述
我有一个多层Python字典作为输入:第一层代表坐标(如x、y、angle_z等),第二层是该坐标的所有可能取值,后续层级代表当前坐标固定时需变更的其他坐标,依此类推。
输入字典
dictionary = { 'x': { 1: { 'y': { 1: {'angle_z': 3}, 4: {'angle_z': 5} } }, 2: { 'z': { 3: {'angle_y': 2} } } }, 'z': { 2: {'y': 10} } }
预期输出
[{'x': 1, 'y': 1, 'angle_z': 3}, {'x': 1, 'y': 4, 'angle_z': 5}, {'x': 2, 'z': 3, 'angle_y': 2}, {'z': 2, 'y': 10}]
要求每个坐标在序列中仅出现一次(如{'x':{1:{'x':2}}}这类情况不允许),函数需尽可能通用,不依赖具体坐标名称,支持任意层数的字典。
我的尝试
我写的递归函数输出结果与预期相差甚远:
def unpack_dictionary(dictionary): if isinstance(dictionary, dict): if len(dictionary) == 1: key = next(iter(dictionary)) rest = dictionary[key] sub_results = unpack_dictionary(rest) return [{key: value, **sub_dict} for value in sub_results for sub_dict in sub_results] else: results = [] for key, value in dictionary.items(): sub_results = unpack_dictionary(value) for sub_dict in sub_results: sub_dict[key] = value results.append(sub_dict) return results else: return [{}]
错误输出
[{'y': {'angle_z': {}, 1: {'angle_z': 3}}, 'angle_z': {}, 1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 'x': {1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 2: {'z': {3: {'angle_y': 2}}}}}, {'y': {'angle_z': {}, 1: {'angle_z': 3}}, 'angle_z': {}, 4: {'angle_z': 5}, 1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 'x': {1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 2: {'z': {3: {'angle_y': 2}}}}}, {'y': {'angle_z': {}, 4: {'angle_z': 5}}, 'angle_z': {}, 1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 'x': {1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 2: {'z': {3: {'angle_y': 2}}}}}, {'y': {'angle_z': {}, 4: {'angle_z': 5}}, 'angle_z': {}, 4: {'angle_z': 5}, 1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 'x': {1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 2: {'z': {3: {'angle_y': 2}}}}}, {'z': {3: {'angle_y': {}}, 'angle_y': {}}, 3: {'angle_y': {}}, 'angle_y': {}, 2: {'z': {3: {'angle_y': 2}}}, 'x': {1: {'y': {1: {'angle_z': 3}, 4: {'angle_z': 5}}}, 2: {'z': {3: {'angle_y': 2}}}}}, {2: {'y': {}}, 'y': {}, 'z': {2: {'y': 10}}}]
解决方案
你的代码核心问题是混淆了字典层级关系,错误地将父级键值嵌套到子结果中,且列表推导式重复遍历子结果导致冗余数据。以下是正确的递归实现:
正确代码
def unpack_dict(input_dict, current=None): if current is None: current = {} results = [] for key, value in input_dict.items(): if isinstance(value, dict): # 遍历当前坐标的所有可能取值 for val, sub_dict in value.items(): # 复制当前累积字典,避免分支间互相干扰 new_current = current.copy() new_current[key] = val # 递归处理子字典,合并结果 results.extend(unpack_dict(sub_dict, new_current)) else: # 叶子节点,生成完整坐标组合 new_current = current.copy() new_current[key] = value results.append(new_current) return results # 测试示例 dictionary = { 'x': { 1: { 'y': { 1: {'angle_z': 3}, 4: {'angle_z': 5} } }, 2: { 'z': { 3: {'angle_y': 2} } } }, 'z': { 2: {'y': 10} } } print(unpack_dict(dictionary))
输出结果
[{'x': 1, 'y': 1, 'angle_z': 3}, {'x': 1, 'y': 4, 'angle_z': 5}, {'x': 2, 'z': 3, 'angle_y': 2}, {'z': 2, 'y': 10}]
代码说明
- 每次递归复制当前累积字典,避免不同分支的坐标组合互相污染。
- 区分嵌套字典节点和叶子节点:嵌套节点继续递归遍历取值,叶子节点直接生成完整组合。
- 顶层自动遍历所有根坐标(如示例中的
x和z),各自展开后合并所有结果。 - 天然满足“每个坐标仅出现一次”的要求,因为递归路径中每个坐标只会被添加一次到累积字典(前提是输入字典本身无重复坐标)。
内容的提问来源于stack exchange,提问作者gioarma
相关产品推荐
相关产品推荐

