如何将依赖树的输出解析为扁平化结构

kyl*_*tor 3 python regex string recursion hierarchical-data

好吧,我完全不知所措.我有一个依赖树解析工具的输出,如下所示:

(S 
    (NP 
        (PRP It)
    )
    (VP
        (VBD said)
        (CLAUSE
            (S
                (NP
                    (DT the)
                    (NN figure)
                )
                (VP 
                    (VBD was)
                    (VBN rounded)
                )
            )
        )
    )
    (PUNC .)
)
Run Code Online (Sandbox Code Playgroud)

这些解析输出保存为纯文本.据我所知,输出基本上是二叉树.我想要的是一个输出文件,其中每个单词都在一个新行上,每个单词包含与该单词相关的所有标签.一个例子是:

It  S   NP  PRP
said    S   VP
the S   VP  CLAUSE  S   NP  DT
figure  S   VP  CLAUSE  S   NP  NN
was S   VP  CLAUSE  S   VP  VBD
rounded S   VP  CLAUSE  S   VP  VBN
. PUNC  S
Run Code Online (Sandbox Code Playgroud)

如何将此输出解析为我正在寻找的输出?我试图使用该pyparsing库,并且已经能够将字符串解析为列表的分层列表,但这不符合我的输出需求.

我认为递归可能是一个很好的候选工具,但我不知道如何将它应用于这个问题.任何有关这方面的帮助将不胜感激 - 甚至伪代码来获得实现的想法.

cs9*_*s95 5

首先,输出转换中存在错误.

要接近解决方案,需要递归.但你不必发明轮子.有一个很好的小模块,pyparsing只是为了这样的任务.我们可以使用递归正则表达式将该字符串转换为嵌套的列表列表:

from pyparsing import nestedExpr

astring = '''(S 
    (NP 
        (PRP It)
    )
    (VP
        (VBD said)
        (CLAUSE
            (S
                (NP
                    (DT the)
                    (NN figure)
                )
                (VP 
                    (VBD was)
                    (VBN rounded)
                )
            )
        )
    )
    (PUNC .)
)'''

expr = nestedExpr('(', ')')
result = expr.parseString(astring).asList()[0]

print(result)
Run Code Online (Sandbox Code Playgroud)

打印出:

['S',
 ['NP', ['PRP', 'It']],
 ['VP',
  ['VBD', 'said'],
  ['CLAUSE',
   ['S',
    ['NP', ['DT', 'the'], ['NN', 'figure']],
    ['VP', ['VBD', 'was'], ['VBN', 'rounded']]]]],
 ['PUNC', '.']]
Run Code Online (Sandbox Code Playgroud)

接下来,我们需要编写一个可以从给定的解析树构建转换的函数.可悲的是,没有简单的方法可以做到这一点.我们需要自己编写一个硬核递归子程序.这是一种方法.使用第n个符号并检索n + 1个符号的所有转换,然后通过将第n个符号附加到这些转换来构建新的转换列表.

听起来有点复杂,但也许代码可以帮助您理解:

def get_rules(rule_list):
    transitions = []

    if len(rule_list) == 2 and isinstance(rule_list[1], str):
        return [rule_list]


    for rule in rule_list[1:]:
        for r in get_rules(rule):
            transitions.append([rule_list[0]] + r)

    return transitions
Run Code Online (Sandbox Code Playgroud)

这很简单.有一个基本案例,如果你到达终端,你将返回一个单例转换.否则以递归方式构建转换.

调用此函数并打印结果接下来完成:

for r in get_rules(result):
    print(r[-1] + '\t' + '\t'.join(r[:-1]))
Run Code Online (Sandbox Code Playgroud)

输出:

It  S   NP  PRP
said    S   VP  VBD
the S   VP  CLAUSE  S   NP  DT
figure  S   VP  CLAUSE  S   NP  NN
was S   VP  CLAUSE  S   VP  VBD
rounded S   VP  CLAUSE  S   VP  VBN
.   S   PUNC
Run Code Online (Sandbox Code Playgroud)

我之前提到你的转换表示不正确.你可以用这个交叉检查,这是正确的答案.