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

Python中将扁平分类层级数据转换为层级数据的最优方案

嘿,这个需求我之前处理过好多次,最靠谱高效的方法就是用哈希表做节点映射,两次遍历搞定,时间复杂度O(n),绝对是最优解。下面给你详细拆解:

核心思路

要把扁平结构转层级,关键是快速找到每个节点的父节点。我们可以先把所有节点用id作为键存到一个字典里(O(1)查找),然后遍历每个节点,把它挂载到对应父节点的children列表中;没有父节点的就是顶级节点,直接加入结果列表。

代码实现

def flat_to_hierarchy(categories):
    # 第一步:构建id到节点的映射,同时给每个节点初始化children列表
    node_map = {}
    for cat in categories:
        # 复制原字典,避免修改原始数据
        node = cat.copy()
        node['children'] = []
        node_map[cat['id']] = node
    
    # 第二步:遍历所有节点,挂载到对应的父节点下
    hierarchy = []
    for node in node_map.values():
        parent_id = node['parent_category_id']
        if parent_id is None:
            # 没有父节点,属于顶级分类
            hierarchy.append(node)
        else:
            # 找到父节点,将当前节点加入其子列表
            # 可选:加个判断避免无效parent_id导致KeyError
            if parent_id in node_map:
                node_map[parent_id]['children'].append(node)
    
    return hierarchy

测试示例

用你提供的数据集(补全category6和7)测试:

d = [
    {'id': 1, 'name': 'category1', 'parent_category_id': None, 'level': 1},
    {'id': 2, 'name': 'category2', 'parent_category_id': None, 'level': 1},
    {'id': 3, 'name': 'category3', 'parent_category_id': None, 'level': 1},
    {'id': 4, 'name': 'category4', 'parent_category_id': 1, 'level': 2},
    {'id': 5, 'name': 'category5', 'parent_category_id': 1, 'level': 2},
    {'id': 6, 'name': 'category6', 'parent_category_id': 4, 'level': 3},
    {'id': 7, 'name': 'category7', 'parent_category_id': 5, 'level': 3}
]

result = flat_to_hierarchy(d)

# 格式化输出查看层级结构
import json
print(json.dumps(result, indent=2))

输出结果会是清晰的层级结构:

[
  {
    "id": 1,
    "name": "category1",
    "parent_category_id": null,
    "level": 1,
    "children": [
      {
        "id": 4,
        "name": "category4",
        "parent_category_id": 1,
        "level": 2,
        "children": [
          {
            "id": 6,
            "name": "category6",
            "parent_category_id": 4,
            "level": 3,
            "children": []
          }
        ]
      },
      {
        "id": 5,
        "name": "category5",
        "parent_category_id": 1,
        "level": 2,
        "children": [
          {
            "id": 7,
            "name": "category7",
            "parent_category_id": 5,
            "level": 3,
            "children": []
          }
        ]
      }
    ]
  },
  {
    "id": 2,
    "name": "category2",
    "parent_category_id": null,
    "level": 1,
    "children": []
  },
  {
    "id": 3,
    "name": "category3",
    "parent_category_id": null,
    "level": 1,
    "children": []
  }
]

为什么这是最优解?

  • 时间效率:两次线性遍历,加上哈希表的O(1)查找,整体时间复杂度是O(n),不管数据集多大都能快速处理。
  • 空间效率:额外用了一个字典存储节点映射,空间复杂度O(n),这是合理的 trade-off。
  • 鲁棒性:不依赖原始数据的排序顺序,不管节点是按什么顺序排列的都能正确生成层级。
  • 可维护性:代码逻辑清晰,容易理解和修改,比如可以快速添加对无效父ID的处理、自定义字段名等。

不推荐的方法:递归查找

有些同学会想到用递归:先找所有顶级节点,然后对每个顶级节点递归查找它的子节点。但这种方法每次找子节点都要遍历整个列表,时间复杂度是O(n²),当数据量较大时(比如上千个节点),性能会差很多,而且如果层级极深还可能触发递归栈溢出,所以不推荐作为最优方案。

内容的提问来源于stack exchange,提问作者Alok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:20:39