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

如何在Python中将结构化字符串解析为Tree数据结构?

解析自定义嵌套笔记格式为树结构

我之前也碰到过类似的自定义嵌套格式解析问题,这种非标准的键值嵌套结构很容易在递归/迭代处理时踩坑——要么是层级跟踪混乱,要么是没处理好分号、大括号的边界。给你分享一个可行的实现方案,分步骤来解决:

1. 先定义树节点结构

首先我们需要一个简单的树节点类,用来存储每个层级的名称和它的子节点:

class TreeNode:
    def __init__(self, name):
        self.name = name
        self.children = []
    
    def __repr__(self, level=0):
        # 自定义打印格式,方便直观查看树结构
        ret = "\t" * level + f"|- {self.name}\n"
        for child in self.children:
            ret += child.__repr__(level + 1)
        return ret

2. 迭代式解析嵌套字符串

用栈来跟踪当前的层级(比递归更适合处理深层嵌套的场景,避免栈溢出),逐个字符处理输入字符串,区分键、子节点和叶子描述:

def parse_note_to_tree(note_str):
    # 预处理:去除多余空格、末尾点号,减少解析干扰
    cleaned = note_str.replace(" ", "").replace(".", "")
    stack = []
    root = None
    current_key = ""
    i = 0
    n = len(cleaned)
    
    while i < n:
        char = cleaned[i]
        if char == ":":
            # 提取当前键(从上次记录的起始位置到当前冒号)
            current_key = cleaned[stack[-1][1] if stack else 0:i].strip()
            i += 1
            # 冒号后是大括号,说明是子节点层级
            if cleaned[i] == "{":
                node = TreeNode(current_key)
                if not root:
                    root = node
                else:
                    stack[-1][0].children.append(node)
                # 将当前节点和下一个键的起始位置压入栈
                stack.append((node, i + 1))
                i += 1
            # 冒号后是普通文本,说明是叶子节点(描述内容)
            else:
                # 找到分号或大括号作为描述的结束标记
                end_idx = cleaned.find(";", i)
                if end_idx == -1:
                    end_idx = cleaned.find("}", i)
                desc = cleaned[i:end_idx].strip()
                leaf_node = TreeNode(desc)
                stack[-1][0].children.append(leaf_node)
                i = end_idx + 1
        elif char == "}":
            # 闭合大括号,回到父节点层级
            stack.pop()
            i += 1
            # 跳过闭合后的分号(同级项分隔符)
            if i < n and cleaned[i] == ";":
                i += 1
        elif char == ";":
            # 分号分隔同级项,更新下一个键的起始位置
            if stack:
                stack[-1] = (stack[-1][0], i + 1)
            i += 1
        else:
            i += 1
    return root

3. 测试示例

用你给出的笔记格式测试一下:

sample_note = """CourseName: { Part 1: { I.I - Intro: { Topic1: { descr1; descr2: { 2.a; 2.b; 2.c. }; descr3. }; Topic2: { descr: { example. }. }. }; I.II - NextChapter: { Topic3: { whatever. }. }. }; Part 2: { II.I - FinalChapter: { content. }. }. }"""
tree = parse_note_to_tree(sample_note)
print(tree)

运行后会输出清晰的树结构:

|- CourseName
	|- Part1
		|- I.I-Intro
			|- Topic1
				|- descr1
				|- descr2
					|- 2a
					|- 2b
					|- 2c
				|- descr3
			|- Topic2
				|- descr
					|- example
		|- I.II-NextChapter
			|- Topic3
				|- whatever
	|- Part2
		|- II.I-FinalChapter
			|- content

你之前失败可能的原因

  • 没有预处理字符串,多余的空格、点号干扰了键和描述的提取;
  • 递归处理时没正确跟踪层级,导致子节点挂载错误;
  • 没区分“冒号后接大括号(子节点)”和“冒号后接文本(叶子描述)”两种情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:12:31