如何在Python中解析字符串中的树?

时间:2018-03-25 17:37:31

标签: python parsing tree text-parsing parse-tree

我已将所有大学笔记格式化如下:

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.
        }.
    }.
}

我希望将它们构建成树数据结构 并且我已经尝试过这样做,在过去几小时内递归和迭代,在网上做了很多研究,但我没有尝试过它。

我已经实施了 Node类(包含self.__value和列表self.__children以及您期望的所有有用方法)以及树类self.__nodes作为词典和其他实用工具方法),因此可以随意使用add_node或{{1}等方法在你的答案中以任何形式的你喜欢。

我正在努力学习的是理解如何构建函数add_child - 理想情况下将字符串def parseTree(s, l)(我的注释)和列表s建立为输入分隔符,即l[":{", ";", "}."]或类似 - 并返回一个树对象,每个节点的值为["{","}"]前面的文本和由{{{{}}分隔的子项列表(如果有) 1}}在文中。

有什么建议吗?

2 个答案:

答案 0 :(得分:3)

这实际上几乎是语法上有效的YAML。简单的替换将使其有效:

data = data.replace(';', ',').replace('.', '')
parsed = yaml.load(data)

答案 1 :(得分:1)

假设您的数据存储在文件中,您可以构建一个简单的类来将结构解析为字典。您可以通过为找到的每个键创建一个新的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.'}
     } 
   }