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

如何用Python从带层级编号的表格构建树形结构?

扁平化层级表格转嵌套树形结构的通用算法与实现思路

我有一张用于表示层级树形结构的扁平化表格(如下表1所示),需要将其转换为等价的嵌套树形结构。请问是否存在通用的算法或实现思路?

已尝试方案

  • 使用Python 3.11开发,基于anytree库进行子类化实现,转换为anytree预期格式的嵌套Python字典也可接受。
  • 自行编写了代码(见代码清单1)但较为粗糙,明确需要判断lvl(层级)的变化,再通过递归将节点添加到对应父节点中,但对递归的触发时机、传递参数及终止条件存在疑问。
  • 疑问:当前数据结构与邻接表类似,能否复用邻接表的相关实现代码?

支撑数据/信息

表1

序号(index)层级(lvl)部件编号(Part #)
10101
21101-1
32101-1A
42101-1B
52101-1C
62101-1D
71101-2
82101-2A
92101-2B
102101-2C

表1数据说明

  • 序号(index):唯一行标识,提供表格全局顺序
  • 层级(lvl):部件的层级,例如0为根节点,1为根节点的子节点等
  • 部件编号(Part #):部件名称

代码清单1

"""
`TreeNode`对象是`anytree.AnyNode`的子类,包含以下属性:
  - `index`: 行号(序号)
  - `lvl`: 层级
  - `parent`: 当前节点的父TreeNode对象。

参数说明:
  - `tn_list`: TreeNode对象列表
  - `parent_node`: 树的根节点,是一个TreeNode对象
  - `current_level`: 标记当前处理的树的层级区域
           [??] 不确定应该用父节点的层级还是当前节点的层级
  - `children`: `parent_node`的子TreeNode对象列表
           [??] 我觉得这个参数可能不需要
"""

def link_TreeNodes(tn_list=None, parent_node=None, children=None, 
                   current_level=None):
    temp_list = []
    children_nodes = []
    
    # 记录上一个节点的层级,用于判断何时停止并将所有子节点添加到父节点
    last_lvl = None
    
    for node in temp_list:
        lvl = getattr(node, 'lvl')
        if last_lvl is None:
            last_lvl = lvl
        else:
            last_lvl = lvl - 1
        
        if lvl == current_level:
            node.parent = parent_node
        elif lvl == current_level + 1:
            children_nodes.append(node)
        elif lvl == current_level - 1:
            # [??] 这里不知道该怎么处理...
            print(f'current_level: {current_level}; lvl: {lvl}')
        
        # 判断是否需要停止当前处理
        if last_lvl == lvl:
            stop = False
            continue
        elif last_lvl == lvl + 1:
            print('停止当前处理,开始处理子节点...')
            stop = True
        
        # 检测到表格层级变化
        if stop:
            if children_nodes:
                parent_node = link_TreeNodes(
                    tn_list=children_nodes, parent_node=parent_node, 
                    current_level=parent_node.lvl+1)
            else:
                return parent_node
            stop = False
    
    # [??] 递归的终止条件是什么?应该返回什么?
    return parent_node

补充1A:测试数据(Python字典格式)

test_data = {'index': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'level': [0, 1, 2, 2, 2, 2, 1, 2, 2, 2], 'part_number': ['101', '101-1', '101-1A', '101-1B', '101-1C', '101-1D', '101-2', '101-2A', '101-2B', '101-2C']}

补充1B:预期输出(嵌套Python字典格式)

correct_output = {
    '101': {'parent': None, 'children': ['101-1', '101-2']},
    '101-1': {'parent': '101', 'children': ['101-1A', '101-1B', '101-1C', '101-1D']},
    '101-1A': {'parent': '101-1', 'children': None},
    '101-1B': {'parent': '101-1', 'children': None},
    '101-1C': {'parent': '101-1', 'children': None},
    '101-1D': {'parent': '101-1', 'children': None},
    '101-2': {'parent': '101', 'children': ['101-2A', '101-2B', '101-2C']},
    '101-2A': {'parent': '101-2', 'children': None},
    '101-2B': {'parent': '101-2', 'children': None},
    '101-2C': {'parent': '101-2', 'children': None}
}

补充1C:调用代码

假设输入数据存储在文件fn中,为纯CSV格式:

def data_reader(fn):
    data = {}
    with open(fn, newline='') as csvfile:
        creader = csv.reader(csvfile, delimiter='\t', quotechar='"')
        for i, row in enumerate(creader):
            if i == 0:
                continue
            data[int(row[0])] = row[1:]
    return data

def convert2TreeNode(data_dict):
    nodes = []
    for k, v in data_dict.items():
        nodes.append(TreeNode.list2TreeNode(dict_key=k, dict_vals=v))
    return nodes

# if __name__ == '__main__':
nodes = convert2TreeNode(data_reader(fn))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:34:52