如何在Python中将带展开列表的扁平字典还原为嵌套字典
实现支持列表还原的扁平化字典逆向函数
已实现的扁平化函数
我已经编写了一个函数,能够接收嵌套结构并将其扁平化,同时展开所有列表元素:
def __flatten_dict_explode_list(d, flat_d, is_list=False, path=[]): if not is_list: for k, v in d.items(): if isinstance(v, dict) and v != {}: __flatten_dict_explode_list(d=v, flat_d=flat_d, path=path + [k]) elif isinstance(v, list) and len(v) > 0 and isinstance(v[0], dict): __flatten_dict_explode_list(d=v, flat_d=flat_d, is_list=True, path=path + [k]) else: key = '/'.join(path) + '/' + k if key not in flat_d: flat_d[key] = v else: for j in range(len(d)): if isinstance(d[j], dict): __flatten_dict_explode_list(d=d[j], flat_d=flat_d, path=path + [f'[{j}]']) else: key = '/'.join(path) + '/' + f'[{j}]' flat_d[key] = d[j] def flatten_dict_explode_list(d): flat_d = dict() __flatten_dict_explode_list(d, flat_d) return flat_d
示例输入与输出
示例输入
d = {'A': { 'B': 1, 'C' : [{'D':1,'E':2,'F' : {'G' : 4}},{'D':2,'E':3,'F' : {'G' : 5}},{'H': [{'J':2}]}] } }
扁平化输出
d_flat = {'A/B' : 1, 'A/C/[0]/D' : 1, 'A/C/[0]/E' : 2, 'A/C/[0]/F/G' : 4, 'A/C/[1]/D' : 2, 'A/C/[1]/E' : 3, 'A/C/[1]/F/G' : 5, 'A/C/[2]/H/[0]/J' : 2 }
需求:逆向还原函数
现在需要编写对应的逆向函数unflatten_dict,接收上述扁平字典,输出还原了列表元素的嵌套字典:
def unflatten_dict(flat_d): # 待实现 return nested_dict
当前尝试的问题
我尝试编写了逆向函数,但无法正确处理列表元素,只能将列表索引作为字典键保留,无法还原为真正的列表:
当前尝试代码
def __unflatten_dict_help(key, val, dictionary, separator, path=[]): parameter_split = key.split(separator) parameter_split = [x for x in parameter_split if x != ""] for path in parameter_split[:-1]: if path not in dictionary: dictionary[path] = {} if type(dictionary[path]) == dict: dictionary = dictionary[path] if len(parameter_split) == 1 and parameter_split[-1] not in dictionary: dictionary[parameter_split[-1]] = {} else: dictionary[parameter_split[-1]] = val def unflatten_dict(d, separator): output_d = dict() for key, val in d.items(): __unflatten_dict_help(key, val, output_d, separator) return output_d
错误输出
调用unflatten_dict(flat_d, "/")得到的输出:
{'A': {'B': 1, 'C': {'[0]': {'D': 1, 'E': 2, 'F': {'G': 4}}, '[1]': {'D': 2, 'E': 3, 'F': {'G': 5}}, '[2]': {'H': {'[0]': {'J': 2} } } } } }
解决方案:支持列表还原的逆向函数
要解决这个问题,核心在于识别路径中的列表索引格式(如[0]),并将其转换为列表结构而非字典键。以下是实现思路和代码:
实现思路
- 拆分每个扁平键的路径段,逐个判断每个段是普通字典键还是列表索引;
- 遍历路径时,遇到普通键则创建/获取字典节点,遇到列表索引则创建/获取列表节点,并根据索引值定位位置;
- 确保列表长度足够容纳当前索引,避免索引越界;
- 最终将值赋值到对应的嵌套位置。
完整实现代码
def unflatten_dict(flat_d, separator='/'): nested = {} def parse_segment(segment): # 判断是否为列表索引段,如"[0]" if segment.startswith('[') and segment.endswith(']'): idx_str = segment[1:-1] if idx_str.isdigit(): return ('list', int(idx_str)) return ('dict', segment) def build_nested(path_segments, value, current): if not path_segments: return value seg_type, seg_val = parse_segment(path_segments[0]) remaining = path_segments[1:] if seg_type == 'dict': if seg_val not in current: current[seg_val] = {} if remaining else value current[seg_val] = build_nested(remaining, value, current[seg_val]) elif seg_type == 'list': # 确保列表长度足够,不足则填充空字典占位(兼容后续嵌套结构) while len(current) <= seg_val: current.append({} if remaining else value) # 若当前位置已有值且是字典,继续递归构建嵌套结构 if isinstance(current[seg_val], dict) and remaining: current[seg_val] = build_nested(remaining, value, current[seg_val]) else: current[seg_val] = value if not remaining else build_nested(remaining, value, {}) return current for key, value in flat_d.items(): path_segments = [s for s in key.split(separator) if s] build_nested(path_segments, value, nested) return nested
测试验证
用示例的d_flat调用该函数:
result = unflatten_dict(d_flat) print(result)
输出结果与原输入一致:
{'A': {'B': 1, 'C': [{'D': 1, 'E': 2, 'F': {'G': 4}}, {'D': 2, 'E': 3, 'F': {'G': 5}}, {'H': [{'J': 2}]}]}}
内容的提问来源于stack exchange,提问作者Kspr
相关产品推荐
相关产品推荐

