You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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]),并将其转换为列表结构而非字典键。以下是实现思路和代码:

实现思路

  1. 拆分每个扁平键的路径段,逐个判断每个段是普通字典键还是列表索引;
  2. 遍历路径时,遇到普通键则创建/获取字典节点,遇到列表索引则创建/获取列表节点,并根据索引值定位位置;
  3. 确保列表长度足够容纳当前索引,避免索引越界;
  4. 最终将值赋值到对应的嵌套位置。

完整实现代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:10:28