如何用Python3实现含嵌套列表的复杂字典扁平化(键以点分隔)
解决嵌套字典含列表的扁平化笛卡尔积转换问题
你的需求是将包含嵌套字典和多层列表的输入,转换为所有列表元素笛卡尔积组合的扁平化字典列表——每个列表的每个元素都要和其他列表的元素一一组合,同时保留所有非列表的公共字段。
现有代码的问题
- 仅处理了第一层列表,无法递归处理嵌套在字典内部的列表(比如
key4nestedListOfDict里的subkeyNested) - 没有处理多个列表的笛卡尔积逻辑,只是逐个展开列表,无法生成所有组合的结果
解决方案代码
from collections.abc import MutableMapping from itertools import product import json def split_common_and_lists(data, parent_key='', separator='.'): common = {} list_dims = [] # 存储每个列表维度的可选键值对集合 for key, value in data.items(): current_key = f"{parent_key}{separator}{key}" if parent_key else key if isinstance(value, MutableMapping): # 递归处理嵌套字典,合并公共部分和列表维度 sub_common, sub_lists = split_common_and_lists(value, current_key, separator) common.update(sub_common) list_dims.extend(sub_lists) elif isinstance(value, list): # 处理列表:生成该维度的所有可选键值组合 options = [] for item in value: if isinstance(item, (MutableMapping, list)): # 递归展开列表元素内部的嵌套结构 item_common, item_lists = split_common_and_lists(item, current_key, separator) if item_lists: # 元素内部有子列表,计算子维度的笛卡尔积并合并 for sub_comb in product(*item_lists): combined = item_common.copy() for sub_dict in sub_comb: combined.update(sub_dict) options.append(combined) else: options.append(item_common) else: # 列表元素为普通值,直接生成键值对 options.append({current_key: value}) list_dims.append(options) else: # 普通键值对加入公共部分 common[current_key] = value return common, list_dims def flatten_to_cartesian_list(data): common, list_dims = split_common_and_lists(data) if not list_dims: return [common] # 计算所有列表维度的笛卡尔积,生成最终结果 result = [] for combo in product(*list_dims): row = common.copy() for part in combo: row.update(part) result.append(row) return result # 测试示例 input_data = { 'key1': 1, 'key2dict': {'subkey1': 1, 'subkey2': 2}, 'key3listOfDict': [ {'subkey3': 3, 'subkey4': 4}, {'subkey5': 5, 'subkey6': 6} ], 'key4nestedListOfDict': [ { 'subkey7': 7, 'subkeyNested': [ {'subkey8': 8}, {'subkey9': 9} ] } ] } output = flatten_to_cartesian_list(input_data) print(json.dumps(output, indent=2))
代码说明
split_common_and_lists函数:- 递归遍历输入数据,分离出所有非列表的公共键值对(存入
common) - 遇到列表时,将列表中每个元素展开为扁平化的键值对字典;如果元素内部还有嵌套列表,会递归计算子维度的笛卡尔积,生成该元素的所有可能组合,最终将整个列表的所有选项存入
list_dims
- 递归遍历输入数据,分离出所有非列表的公共键值对(存入
flatten_to_cartesian_list函数:- 使用
itertools.product计算所有列表维度的笛卡尔积,将每个组合的键值对与公共部分合并,生成最终的字典列表
- 使用
运行上述代码后,会输出你需要的4个扁平化字典的列表,完全匹配预期结果。
内容的提问来源于stack exchange,提问作者shachar0n
相关产品推荐
相关产品推荐

