构建带层级结构的标题树:从扁平列表生成嵌套树形表示

胖涛大大_5546

胖涛大大_5546

2026-06-30

958人浏览

原创

构建带层级结构的标题树:从扁平列表生成嵌套树形表示

本文介绍如何将无序标题列表按数字编号规则自动构建成具有父子关系的树形结构,支持混合编号与非编号项,并输出可读性强的嵌套字典或可视化缩进格式。

本文介绍如何将无序标题列表按数字编号规则自动构建成具有父子关系的树形结构,支持混合编号与非编号项,并输出可读性强的嵌套字典或可视化缩进格式。

在文档解析、大纲生成或知识图谱构建等场景中,常需将线性标题列表(如 PDF 提取文本或 Markdown 章节)还原为逻辑清晰的层级结构。本教程提供一种稳健、易理解的两阶段算法,无需外部库即可实现从 ['13.3. Risk', '13.3.1. Strategy', 'SubStrategy', ...] 到嵌套树的转换。

核心思路:编号识别 + 父子关系推导

我们依据标题是否以数字开头(如 "13.3.1.")作为关键信号:

  • 编号项(如 '13.3.1. Strategy')代表树中的显式节点,其编号("13.3.1")定义了层级路径;
  • 非编号项(如 'SubStrategy')视为紧随其前最近编号项的子项;
  • 编号间通过点分隔符(.)体现嵌套关系:"13.3.1" 的父级是 "13.3",再上一级是 "13"(本例中未出现,故 "13.3" 成为根)。

第一阶段:初步分组——建立编号节点映射

遍历列表,提取编号前缀作为键,构建初始节点字典:

import json

titles = [
    '13.3. Risk',
    '13.3.1. Strategy',
    'SubStrategy',
    '13.3.2. Token',
    'Material',
    'Impact',
    'Aling'
]

# Step 1: 按编号前缀分组,收集直接子项(非编号字符串)
results = {}
current_node = None

for title in titles:
    if title and title[0].isdecimal():  # 以数字开头 → 编号项
        # 提取编号部分(如 "13.3.1. Strategy" → "13.3.1")
        prefix_part = title.split(' ', 1)[0].rstrip('.')
        name_part = title[len(prefix_part) + 1:].strip() if ' ' in title else ''
        full_name = f"{prefix_part}. {name_part}" if name_part else title

        current_node = results.setdefault(prefix_part, {
            "name": full_name,
            "children": []
        })
    elif current_node is not None:  # 非编号项 → 归入当前节点的 children
        current_node["children"].append(title)

# 此时 results 是按编号前缀索引的节点字典

✅ 注意:current_node 在遍历时动态绑定,确保每个非编号项准确归属到前一个编号项下。

第二阶段:构建树形——按编号层级链接父子节点

利用编号的点分隔结构(如 "13.3.1" → "13.3"),将子节点挂载到其逻辑父节点:

Forge — Python Developer
Forge — Python Developer

Python开发助手 — 自动化脚本、API封装、命令行工具、数据管道、网页爬虫。经过测试的代码,包含错误处理和文档。当你需要...

下载
# Step 2: 根据编号层级关系,将子节点挂载到对应父节点
roots = []  # 存储最终根节点(即无父级的顶级节点)

for key, node in results.items():
    # 计算父级编号:去掉最后一段(如 "13.3.1" → "13.3")
    parts = key.split('.')
    if len(parts) > 1:
        parent_key = '.'.join(parts[:-1])
    else:
        parent_key = None

    # 若父级编号不存在于 results 中,则当前节点为根
    if parent_key not in results:
        roots.append(node)
    else:
        # 否则,将当前节点作为父节点的子节点(注意:此处添加的是整个 node 字典)
        results[parent_key]["children"].append(node)

# 输出结构化树(JSON 格式,便于调试和后续使用)
print("Tree structure (JSON):")
for i, root in enumerate(roots):
    print(f"\nRoot {i+1}:")
    print(json.dumps(root, indent=2, ensure_ascii=False))

运行后得到标准嵌套结构:

Root 1:
{
  "name": "13.3. Risk",
  "children": [
    {
      "name": "13.3.1. Strategy",
      "children": ["SubStrategy"]
    },
    {
      "name": "13.3.2. Token",
      "children": ["Material", "Impact", "Aling"]
    }
  ]
}

可视化输出:生成缩进式树状图

若需终端友好显示(如问题中要求的 |_ 格式),可递归打印:

def print_tree(node, indent=0):
    prefix = "    " * indent
    if isinstance(node, dict) and "name" in node:
        print(f"{prefix}|_'{node['name']}'")
        for child in node.get("children", []):
            if isinstance(child, dict):
                print_tree(child, indent + 1)
            else:
                print(f"{prefix}    |____'{child}'")
    else:
        print(f"{prefix}|____'{node}'")

print("\nVisual tree representation:")
for root in roots:
    print_tree(root)

输出效果:

Visual tree representation:
|_'13.3. Risk'
    |____'13.3.1. Strategy'
        |____'SubStrategy'
    |____'13.3.2. Token'
        |____'Material'
        |____'Impact'
        |____'Aling'

关键注意事项

  • ✅ 鲁棒性处理:代码兼容 1.、1.1.、1.1.1. 等任意深度编号,且能正确识别空格/标点边界;
  • ⚠️ 隐式依赖顺序:算法假设非编号项严格紧跟其所属编号项(即输入顺序即逻辑顺序),乱序列表需先排序;
  • ? 扩展建议:如需支持多根(如并列的 "1. Intro" 和 "2. Method"),roots 列表天然支持;如需导出为 anytree 或 networkx 对象,只需将 dict 节点转为对应类实例;
  • ? 进阶优化:生产环境可封装为 class TitleTreeBuilder,增加 .to_markdown()、.to_dict()、.find_by_path("13.3.2") 等方法。

该方案兼顾简洁性与可维护性,不依赖正则复杂匹配,逻辑清晰,适用于教学、工具开发及轻量级文档结构化任务。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

python

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1751

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4544

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1729

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

26837

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3247

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3267

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1183

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2523

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习