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

Python实现父子节点层级排序与坐标定位问题求助

问题解决:树形节点排序与坐标计算

需求说明

  • 将字典列表按父节点下的层级顺序排列
  • 为每个节点计算x、y坐标:子节点x轴相对父节点偏移20px;y轴根据上方所有节点总数,每个节点偏移20px

当前数据列表

my_list = [
    {"name": "AAA", "parent": "none", "children": ["BBB", "CCC", "DDD"], "x": 0, "y": 0},
    {"name": "BBB", "parent": "AAA", "children": ["EEE"], "x": 0, "y": 0},
    {"name": "CCC", "parent": "AAA", "children": ["FFF"], "x": 0, "y": 0},
    {"name": "DDD", "parent": "AAA", "children": [], "x": 0, "y": 0},
    {"name": "EEE", "parent": "BBB", "children": [], "x": 0, "y": 0},
    {"name": "FFF", "parent": "CCC", "children": [], "x": 0, "y": 0},
    {"name": "GGG", "parent": "none", "children": ["HHH"], "x": 0, "y": 0},
    {"name": "HHH", "parent": "GGG", "children": [], "x": 0, "y": 0},
]

期望输出

AAA (0, 0)
    BBB (20, 20)
        EEE (40, 40)
    CCC (20, 60)
        FFF (40, 80)
    DDD (20, 100)
GGG (0, 120)
    HHH (0, 140)

尝试的代码(存在问题)

for value in name_list:
    if value["parent"] == "none":
        loop = True
        loop_list = value["children"]
        while loop:
            for child_name in loop_list:
                child = get_item(child_name)

                if len(child["children"]) != 0:
                    loop_list = child["children"]

                print("result") ;(

解决方案

步骤1:构建节点映射字典

先将列表转换为以节点名称为键的字典,方便快速查找节点:

node_map = {node["name"]: node for node in my_list}

步骤2:递归遍历计算坐标并排序

使用深度优先递归遍历,维护当前y坐标偏移,处理节点顺序和坐标赋值:

def process_tree(root_name, current_x, current_y, node_map, result):
    node = node_map[root_name]
    # 赋值当前节点坐标
    node["x"] = current_x
    node["y"] = current_y
    result.append(node)
    # 处理子节点,更新y坐标
    next_y = current_y + 20
    for child_name in node["children"]:
        next_y = process_tree(child_name, current_x + 20, next_y, node_map, result)
    # 返回当前分支处理完后的下一个y坐标
    return next_y

# 处理所有根节点
sorted_list = []
current_global_y = 0
for node in my_list:
    if node["parent"] == "none":
        current_global_y = process_tree(node["name"], 0, current_global_y, node_map, sorted_list)

步骤3:按树形格式输出

根据节点x坐标计算缩进,输出符合要求的格式:

for node in sorted_list:
    indent = "    " * (node["x"] // 20)
    print(f"{indent}{node['name']} ({node['x']}, {node['y']})")

完整代码

my_list = [
    {"name": "AAA", "parent": "none", "children": ["BBB", "CCC", "DDD"], "x": 0, "y": 0},
    {"name": "BBB", "parent": "AAA", "children": ["EEE"], "x": 0, "y": 0},
    {"name": "CCC", "parent": "AAA", "children": ["FFF"], "x": 0, "y": 0},
    {"name": "DDD", "parent": "AAA", "children": [], "x": 0, "y": 0},
    {"name": "EEE", "parent": "BBB", "children": [], "x": 0, "y": 0},
    {"name": "FFF", "parent": "CCC", "children": [], "x": 0, "y": 0},
    {"name": "GGG", "parent": "none", "children": ["HHH"], "x": 0, "y": 0},
    {"name": "HHH", "parent": "GGG", "children": [], "x": 0, "y": 0},
]

node_map = {node["name"]: node for node in my_list}
sorted_list = []

def process_tree(root_name, current_x, current_y, node_map, result):
    node = node_map[root_name]
    node["x"] = current_x
    node["y"] = current_y
    result.append(node)
    next_y = current_y + 20
    for child_name in node["children"]:
        next_y = process_tree(child_name, current_x + 20, next_y, node_map, result)
    return next_y

current_global_y = 0
for node in my_list:
    if node["parent"] == "none":
        current_global_y = process_tree(node["name"], 0, current_global_y, node_map, sorted_list)

for node in sorted_list:
    indent = "    " * (node["x"] // 20)
    print(f"{indent}{node['name']} ({node['x']}, {node['y']})")

代码说明

  • 节点映射字典:避免每次遍历列表查找节点,提升处理效率。
  • 递归遍历:深度优先遍历保证节点层级顺序正确,同时传递更新y坐标,确保每个节点的y值为上方所有节点总数乘以20。
  • 缩进计算:根据x坐标(每20px对应一级)生成缩进,实现树形输出效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:45:34