Python如何获取树结构中所有可能路径组成的嵌套列表
原有代码问题分析
你当前的实现无法生成正确路径,核心原因有3点:
- 所有节点都追加到同一个共享列表中,没有区分不同分支的独立路径,最终只会得到平铺的节点集合
- 缺少回溯逻辑:遍历完某个子分支后,没有清除当前分支的节点状态,导致不同分支的节点会混杂在同一条路径中
- 没有在路径终点(叶子节点)保存当前路径的独立副本,递归过程中的列表修改会影响已经存入结果的路径
正确实现方案
采用深度优先遍历+回溯的思路实现:维护一个临时列表存储当前遍历路径,每进入一个节点就将其加入路径,遍历完该节点所有子节点后将其移出路径(回溯),遇到叶子节点时将当前路径的副本存入最终结果。
适配CategoryPath类型的实现
返回List[List[CategoryPath]]格式的结果,匹配你现有代码的类型定义:
from typing import List # 若你的项目中已经定义过这两个类可以直接忽略,这里仅作类型示意 class CategoriesTreeNodeFull: def __init__(self, id: int, name: str, children: List['CategoriesTreeNodeFull']): self.id = id self.name = name self.children = children class CategoryPath: def __init__(self, id: int, name: str): self.id = id self.name = name def create_category_paths_from_children(root_nodes: List[CategoriesTreeNodeFull]) -> List[List[CategoryPath]]: result = [] def dfs(current_node: CategoriesTreeNodeFull, current_path: List[CategoryPath]): # 将当前节点加入路径 current_path.append(CategoryPath(name=current_node.name, id=current_node.id)) if not current_node.children: # 到达叶子节点,存入当前路径的副本(必须存副本,否则后续回溯会修改已存入的结果) result.append(current_path.copy()) else: # 递归遍历所有子节点 for child in current_node.children: dfs(child, current_path) # 回溯:移除当前节点,切换到其他分支 current_path.pop() # 遍历所有根节点启动递归 for root in root_nodes: dfs(root, []) return result
直接返回ID嵌套列表的实现
如果需要直接得到你给出的纯ID嵌套列表格式(如[[24,137,237], ...]),可以用更简洁的版本:
def create_category_id_paths(root_nodes: List[CategoriesTreeNodeFull]) -> List[List[int]]: result = [] def dfs(current_node: CategoriesTreeNodeFull, current_path: List[int]): current_path.append(current_node.id) if not current_node.children: result.append(current_path.copy()) else: for child in current_node.children: dfs(child, current_path) current_path.pop() for root in root_nodes: dfs(root, []) return result
注意事项
你给出的原始输入结构中,id=154的节点和id=155的节点是平级关系,这种情况下输出的路径会包含[24,151,154],不会出现[24,151,155,154]。如果要得到你期望输出中的[24,151,155,154],需要将id=154的节点移动到id=155节点的children列表中,调整后运行代码即可得到和期望完全一致的结果。
调用测试示例
# 工具函数:将字典格式的树数据转换为节点对象 def build_tree(raw_data: list) -> List[CategoriesTreeNodeFull]: node_list = [] for item in raw_data: children = build_tree(item.get("children", [])) # name字段可替换为你实际数据中的name值 node_list.append(CategoriesTreeNodeFull(id=item["id"], name=str(item["id"]), children=children)) return node_list # 调整后的数据(154放到155的children下,匹配你的期望输出) raw_tree = [ { "id": 24, "children": [ { "id": 137, "children": [{"id":237,"children":[]}, {"id":251,"children":[]}] }, { "id": 151, "children": [ {"id":155, "children":[{"id":154,"children":[]}]} ] } ] } ] root_nodes = build_tree(raw_tree) # 打印ID路径结果 print(create_category_id_paths(root_nodes)) # 输出:[[24, 137, 237], [24, 137, 251], [24, 151, 155], [24, 151, 155, 154]]
内容的提问来源于stack exchange,提问作者Daniel Gašparík
相关产品推荐
相关产品推荐

