如何从 Python 中的字符串解析树?
How to parse a tree from a string in Python?
我的大学笔记格式如下:
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.
}.
}.
}
我想将它们构造成树数据结构,我已经尝试这样做,递归地和迭代地,在过去的几个小时里,我在网上做了很多研究,但是 none 我的尝试都奏效了。
我已经实现了一个 Node class(带有 self.__value
和一个列表 self.__children
以及您期望的所有有用方法从它)以及 Tree class(self.__nodes
作为 dictionary 和其他实用方法),所以您可以在回答中随意使用 add_node
或 add_child
等方法。
我正在努力了解如何构建函数 def parseTree(s, l)
- 理想情况下将字符串 s
(我的笔记)和列表 l
作为输入分隔符,即 [":{", ";", "}."]
或 ["{","}"]
或类似的 - 和 returns 一个树对象,每个节点的值都是 :{
之前的文本和一个子列表(如果有)文中用;
分隔。
有什么建议吗?
这实际上是语法上几乎有效的 YAML。一个简单的替换将使其有效:
data = data.replace(';', ',').replace('.', '')
parsed = yaml.load(data)
假设你的数据存储在一个文件中,你可以构建一个简单的class来将结构解析成字典。您可以通过为找到的每个键创建一个新的 Notes
对象来递归遍历数据:
file_data = filter(None, [i.strip('\n') for i in open('filename.txt')])
import re
class Notes:
def __init__(self, token_data):
self.token_data = token_data
self.current_dict = {}
self.current_vals = []
self.parse()
def parse(self):
while True:
start = next(self.token_data, None)
if not start or "}" in start:
break
if start.endswith('{'):
note = Notes(self.token_data)
final_result = filter(lambda x:x, note.current_vals + [note.current_dict]) if note.current_vals else note.current_dict
self.current_dict[re.findall('[\w\s\-\.]+', re.sub('^\s+', '', start))[0]] = final_result[0] if isinstance(final_result, list) and len(final_result) == 1 else final_result
self.token_data = note.token_data
else:
self.current_vals.append(re.sub('^\s+', '', start))
course_notes = Notes(iter(file_data)).current_dict
输出:
{'CourseName':
{'Part 1':
{'I.I - Intro':
{'Topic1': ['descr1;',
'descr3.',
{'descr2': ['2.a;',
'2.b;',
'2.c.']
}
],
'Topic2': {'descr': 'example.'}
},
'I.II - NextChapter':
{'Topic3': 'whatever.'}
},
'Part 2':{'II.I - FinalChapter': 'content.'}
}
}
我的大学笔记格式如下:
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.
}.
}.
}
我想将它们构造成树数据结构,我已经尝试这样做,递归地和迭代地,在过去的几个小时里,我在网上做了很多研究,但是 none 我的尝试都奏效了。
我已经实现了一个 Node class(带有 self.__value
和一个列表 self.__children
以及您期望的所有有用方法从它)以及 Tree class(self.__nodes
作为 dictionary 和其他实用方法),所以您可以在回答中随意使用 add_node
或 add_child
等方法。
我正在努力了解如何构建函数 def parseTree(s, l)
- 理想情况下将字符串 s
(我的笔记)和列表 l
作为输入分隔符,即 [":{", ";", "}."]
或 ["{","}"]
或类似的 - 和 returns 一个树对象,每个节点的值都是 :{
之前的文本和一个子列表(如果有)文中用;
分隔。
有什么建议吗?
这实际上是语法上几乎有效的 YAML。一个简单的替换将使其有效:
data = data.replace(';', ',').replace('.', '')
parsed = yaml.load(data)
假设你的数据存储在一个文件中,你可以构建一个简单的class来将结构解析成字典。您可以通过为找到的每个键创建一个新的 Notes
对象来递归遍历数据:
file_data = filter(None, [i.strip('\n') for i in open('filename.txt')])
import re
class Notes:
def __init__(self, token_data):
self.token_data = token_data
self.current_dict = {}
self.current_vals = []
self.parse()
def parse(self):
while True:
start = next(self.token_data, None)
if not start or "}" in start:
break
if start.endswith('{'):
note = Notes(self.token_data)
final_result = filter(lambda x:x, note.current_vals + [note.current_dict]) if note.current_vals else note.current_dict
self.current_dict[re.findall('[\w\s\-\.]+', re.sub('^\s+', '', start))[0]] = final_result[0] if isinstance(final_result, list) and len(final_result) == 1 else final_result
self.token_data = note.token_data
else:
self.current_vals.append(re.sub('^\s+', '', start))
course_notes = Notes(iter(file_data)).current_dict
输出:
{'CourseName':
{'Part 1':
{'I.I - Intro':
{'Topic1': ['descr1;',
'descr3.',
{'descr2': ['2.a;',
'2.b;',
'2.c.']
}
],
'Topic2': {'descr': 'example.'}
},
'I.II - NextChapter':
{'Topic3': 'whatever.'}
},
'Part 2':{'II.I - FinalChapter': 'content.'}
}
}