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

时间:2017-07-06 00:57:39

标签: 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 .)
)

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

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

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

我认为递归可能是一个很好的候选工具,但我不知道如何将它应用于这个问题。任何有关这方面的帮助都将受到赞赏 - 即使是伪代码也可以获得实现的想法。

1 个答案:

答案 0 :(得分: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)

打印出来:

['S',
 ['NP', ['PRP', 'It']],
 ['VP',
  ['VBD', 'said'],
  ['CLAUSE',
   ['S',
    ['NP', ['DT', 'the'], ['NN', 'figure']],
    ['VP', ['VBD', 'was'], ['VBN', 'rounded']]]]],
 ['PUNC', '.']]

接下来,我们需要编写一个可以从给定的解析树构建转换的函数。可悲的是,没有简单的方法可以做到这一点。我们自己需要编写一个硬核递归子程序。这是一种方法。使用第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

非常简单。这是一个基本案例,如果您到达终端,您将返回单例转换。否则以递归方式构建转换。

调用此功能并打印结果:

for r in get_rules(result):
    print(r[-1] + '\t' + '\t'.join(r[:-1]))

输出:

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

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