python - 在python中将字符串转换为树结构

标签 python

我在 python 中有一个如下形式的字符串:

line a
line b
  line ba
  line bb
    line bba
  line bc
line c
  line ca
    line caa
line d

你可以明白这一点。它实际上采用与 python 代码本身非常相似的形式,因为有一行,在该行下方,缩进表示 block 的一部分,以最近的较小缩进行开头。

我需要做的是将这段代码解析成一个树结构,这样每个根级别的行都是一个字典的键,它的值是一个代表所有子行的字典。所以上面的内容是:

{
'line a' => {},
'line b' => {
  'line ba' => {},
  'line bb' => {
    'line bba' => {}
    },
  'line bc' => {}
  },
'line c' => {
  'line ca' => {
    'line caa' => {}
    },
  },
'line d' => {}
}

这是我得到的:

def parse_message_to_tree(message):
    buf = StringIO(message)
    return parse_message_to_tree_helper(buf, 0)

def parse_message_to_tree_helper(buf, prev):
    ret = {}
    for line in buf:
        line = line.rstrip()
        index = len(line) - len(line.lstrip())
        print (line + " => " + str(index))
        if index > prev:
            ret[line.strip()] = parse_message_to_tree_helper(buf, index)
        else:
            ret[line.strip()] = {}

    return ret

打印显示被剥离的行和索引为 0。我不认为 lstrip() 是一个突变器,但无论哪种方式,索引应该仍然是准确的。

任何建议都是有帮助的。

编辑:不确定之前出了什么问题,但我再次尝试并且它更接近工作,但仍然不太正确。这是我现在拥有的:

{'line a': {},
 'line b': {},
 'line ba': {'line bb': {},
             'line bba': {'line bc': {},
                          'line c': {},
                          'line ca': {},
                          'line caa': {},
                          'line d': {}}}}

最佳答案

正如之前已经指出的那样,str.lstrip() 不是突变器,索引在我的系统中也变得准确了。

但问题是,当您意识到该行的索引增加时,line 实际上指向增加的索引行,例如,在第一种情况下,我们注意到索引为line 在 line ba 增加,所以 line 指向 line ba ,然后在你的 if 条件下,你做-

ret[line.strip()] = parse_message_to_tree_helper(buf, index)

这是错误的,因为您会将 parse_message_to_tree_helper() 返回的任何内容设置为 line ba,而不是其实际父级。

此外,一旦你在函数内部递归,除非文件被完全读取,否则你不会出来,但是当缩进减少时,某一行在字典中的存储级别取决于它从递归中出来。

我不确定是否有任何内置库可以帮助您执行此操作,但是我能够想出一个代码(很大程度上基于您的代码)-

def parse_message_to_tree(message):
    buf = StringIO(message)
    return parse_message_to_tree_helper(buf, 0, None)[0]

def parse_message_to_tree_helper(buf, prev, prevline):
    ret = {}
    index = -1
    for line in buf:
        line = line.rstrip()
        index = len(line) - len(line.lstrip())
        print (line + " => " + str(index))
        if index > prev:
            ret[prevline.strip()],prevline,index = parse_message_to_tree_helper(buf, index, line)
            if index < prev:
                return ret,prevline,index
            continue
        elif not prevline:
            ret[line.strip()] = {}
        else:
            ret[prevline.strip()] = {}
        if index < prev:
            return ret,line,index
        prevline = line
    if index == -1:
        ret[prevline.strip()] = {}
        return ret,None,index
    if prev == index:
        ret[prevline.strip()] = {}
    return ret,None,0

示例/演示 -

>>> print(s)
line a
line b
  line ba
  line bb
    line bba
  line bc
line c
  line ca
    line caa
>>> def parse_message_to_tree(message):
...     buf = StringIO(message)
...     return parse_message_to_tree_helper(buf, 0, None)[0]
...
>>> def parse_message_to_tree_helper(buf, prev, prevline):
...     ret = {}
...     index = -1
...     for line in buf:
...         line = line.rstrip()
...         index = len(line) - len(line.lstrip())
...         print (line + " => " + str(index))
...         if index > prev:
...             ret[prevline.strip()],prevline,index = parse_message_to_tree_helper(buf, index, line)
...             if index < prev:
...                 return ret,prevline,index
...             continue
...         elif not prevline:
...             ret[line.strip()] = {}
...         else:
...             ret[prevline.strip()] = {}
...         if index < prev:
...             return ret,line,index
...         prevline = line
...     if index == -1:
...         ret[prevline.strip()] = {}
...         return ret,None,index
...     if prev == index:
...         ret[prevline.strip()] = {}
...     return ret,None,0
...
>>> pprint.pprint(parse_message_to_tree(s))
line a => 0
line b => 0
  line ba => 2
  line bb => 2
    line bba => 4
  line bc => 2
line c => 0
  line ca => 2
    line caa => 4
{'line a': {},
 'line b': {'line ba': {}, 'line bb': {'line bba': {}}, 'line bc': {}},
 'line c': {'line ca': {'line caa': {}}}}
>>> s = """line a
... line b
...   line ba
...   line bb
...     line bba
...   line bc
... line c
...   line ca
...     line caa
... line d"""
>>> pprint.pprint(parse_message_to_tree(s))
line a => 0
line b => 0
  line ba => 2
  line bb => 2
    line bba => 4
  line bc => 2
line c => 0
  line ca => 2
    line caa => 4
line d => 0
{'line a': {},
 'line b': {'line ba': {}, 'line bb': {'line bba': {}}, 'line bc': {}},
 'line c': {'line ca': {'line caa': {}}},
 'line d': {}}

您需要测试代码是否有更多错误或遗漏的案例。

关于python - 在python中将字符串转换为树结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32101253/

相关文章:

python : Calling functions from inside another function parameter

python - 如何使我的 session.get() 链接到变量?

python - 应用于整个数据集的函数

python - 使用Python Dom向xml文件添加具有相同节点名称但不同属性的节点

php - 用于文件/图像操作的有效解释型编程语言

python - 结合多个 Pandas read_csv 和/或 file.readline()

python - 为什么 pandas 系列返回我的 numpy datetime64 数组的元素作为时间戳?

python - 使用Python,当输入字符串为aaabbcddddd时,如何将输出字符串打印为-> aaa3bb2c1ddddd5

python - 如何访问管道中包含的模型中的最佳估计器参数?

python - 使用 Scala 或 Python 列出存储在 Hadoop HDFS 上的 Spark 集群中可用的所有文件?