如何用Python从带层级编号的表格构建树形结构?
扁平化层级表格转嵌套树形结构的通用算法与实现思路
我有一张用于表示层级树形结构的扁平化表格(如下表1所示),需要将其转换为等价的嵌套树形结构。请问是否存在通用的算法或实现思路?
已尝试方案
- 使用Python 3.11开发,基于
anytree库进行子类化实现,转换为anytree预期格式的嵌套Python字典也可接受。 - 自行编写了代码(见代码清单1)但较为粗糙,明确需要判断
lvl(层级)的变化,再通过递归将节点添加到对应父节点中,但对递归的触发时机、传递参数及终止条件存在疑问。 - 疑问:当前数据结构与邻接表类似,能否复用邻接表的相关实现代码?
支撑数据/信息
表1
| 序号(index) | 层级(lvl) | 部件编号(Part #) |
|---|---|---|
| 1 | 0 | 101 |
| 2 | 1 | 101-1 |
| 3 | 2 | 101-1A |
| 4 | 2 | 101-1B |
| 5 | 2 | 101-1C |
| 6 | 2 | 101-1D |
| 7 | 1 | 101-2 |
| 8 | 2 | 101-2A |
| 9 | 2 | 101-2B |
| 10 | 2 | 101-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
相关产品推荐
相关产品推荐

