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

Python递归转换路径字典为树形结构结果异常,求排查错误

字典转树形结构的递归函数错误分析

问题场景

输入表示树路径的Python字典:

{
  "example": {
    "dir2": {
      "file4": {},
      "file5": {}
    },
    "dir1": {
      "file1": {},
      "file2": {},
      "dir5": {},
      "dir4": {
        "file3": {}
      }
    }
  }
}

期望转换为如下树形结构:

{
  "name": "example",
  "children": [
    {
      "name": "dir2",
      "children": [
        {
          "name": "file4"
        },
        {
          "name": "file5"
        }
      ]
    },
    {
      "name": "dir1",
      "children": [
        {
          "name": "file1"
        },
        {
          "name": "file2"
        },
        {
          "name": "dir5",
          "children": []
        },
        {
          "name": "dir4",
          "children": [
            {
              "name": "file3"
            }
          ]
        }
      ]
    }
  ]
}

编写的递归函数如下:

import json

def convert_dict(dic):
    name = list(dic.keys())[0]
    d = {'name': name}
    if dic[name]:
        d['children']=[convert_dict(dic[name][x]) for x in list(dic[name].keys())]
    return d

tree_dict = {
  "example": {
    "dir2": {
      "file4": {},
      "file5": {}
    },
    "dir1": {
      "file1": {},
      "file2": {},
      "dir5": {},
      "dir4": {
        "file3": {}
      }
    }
  }
}

print(json.dumps(convert_dict(tree_dict), indent=2))

运行后仅得到部分节点:

{
  "name": "example",
  "children": [
    {
      "name": "file4"
    },
    {
      "name": "file1"
    }
  ]
}

错误原因

  1. 节点与子项的对应关系逻辑错误:
    函数每次提取传入字典的第一个键作为当前节点名称,但遍历子节点时,传入的是子键对应的完整字典(比如dir2对应的{"file4": {}, "file5": {}})。此时函数会错误地将这个字典的第一个键(file4)当作当前节点,直接跳过了dir2这个中间节点。
  2. 空字典节点未处理:
    对于原字典中值为空字典的节点(比如dir5),原函数未添加"children": []字段,不符合期望格式。

修正后的代码

方案1:拆分函数,明确节点构建逻辑

import json

def build_node(name, children_dict):
    node = {"name": name}
    # 递归构建子节点,空字典则生成空children列表
    node["children"] = [build_node(child_name, child_content) for child_name, child_content in children_dict.items()] if children_dict else []
    return node

def convert_dict(dic):
    # 提取根节点名称和对应的子字典
    root_name = list(dic.keys())[0]
    return build_node(root_name, dic[root_name])

tree_dict = {
  "example": {
    "dir2": {
      "file4": {},
      "file5": {}
    },
    "dir1": {
      "file1": {},
      "file2": {},
      "dir5": {},
      "dir4": {
        "file3": {}
      }
    }
  }
}

print(json.dumps(convert_dict(tree_dict), indent=2))

方案2:直接修正原递归逻辑

import json

def convert_dict(dic):
    name = list(dic.keys())[0]
    node = {"name": name}
    children_dict = dic[name]
    if children_dict:
        children = []
        for child_name, child_content in children_dict.items():
            child_node = {"name": child_name}
            # 递归处理子内容,需包装为单键字典适配函数输入
            if child_content:
                child_node["children"] = convert_dict({child_name: child_content})["children"]
            else:
                child_node["children"] = []
            children.append(child_node)
        node["children"] = children
    else:
        node["children"] = []
    return node

tree_dict = {
  "example": {
    "dir2": {
      "file4": {},
      "file5": {}
    },
    "dir1": {
      "file1": {},
      "file2": {},
      "dir5": {},
      "dir4": {
        "file3": {}
      }
    }
  }
}

print(json.dumps(convert_dict(tree_dict), indent=2))

修正逻辑说明

  • 明确每个节点的name对应原字典的键,子节点由该键对应的字典生成,避免了原函数跳过中间节点的问题。
  • 主动为空字典节点添加"children": []字段,完全匹配期望输出格式。
  • 拆分build_node函数的方案更直观,将节点名称与子字典的处理逻辑分离,降低递归复杂度。

内容的提问来源于stack exchange,提问作者voron.run

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:55:08