【问题标题】:Printing balanced parenthesis for Penn Tree Bank format为 Penn Tree Bank 格式打印平衡括号
【发布时间】:2015-04-04 19:04:40
【问题描述】:

我正在尝试打印 Penn Tree Bank 样式的解析,但我似乎无法正确平衡括号(令人沮丧 - 解析器运行良好,但我无法正确打印输出!)关于递归函数的任何提示或技巧可以做到这一点?

这是我当前的打印方法,我调用从解析的开始节点开始的函数。

def print_tree(current_node, parents, side):
    print(parents)
    for i in range(parents):
        print("     ", " ", end="")
    if current_node.is_terminal:
        if side == 'left':
            print("(" + current_node.lhs, current_node.word_label + " )")
        else: 
            print("(" + current_node.lhs, current_node.word_label +")", "", end ="")
            for i in range(parents):
                print(")", "", end="")
            print()
    else:
        print("( " +current_node.lhs)
    if current_node.left_child != None:
        print_tree(current_node.left_child, parents+1, 'left')
    if current_node.right_child != None:
        print_tree(current_node.right_child, parents+1, 'right')

我得到的结果:

( TOP
              ( S_VP
                     (VB 'List' )
                     ( NP
                            ( NP
                                   (DT 'the' )
                                   (NNS 'flights') ) ) ) ) ) 
                            ( PP
                                   ( PP
                                          (IN 'from' )
                                          (NP_NNP 'Baltimore') ) ) ) ) ) ) 
                                   ( PP
                                          (TO 'to' )
                                          ( NP
                                                 (NP_NNP 'Seattle' )
                                                 ( NP
                                                        ( NP
                                                               (DT 'that' )
                                                               (NN 'stop') ) ) ) ) ) ) ) ) ) 
                                                        ( PP
                                                               (IN 'in' )
                                                               (NP_NNP 'Minneapolis') ) ) ) ) ) ) ) ) ) 
              (PUNC '.') ) ) 

想要的结果:

( TOP
              ( S_VP
                     (VB 'List' )
                     ( NP
                            ( NP
                                   (DT 'the' )
                                   (NNS 'flights') )
                            ( PP
                                   ( PP
                                          (IN 'from' )
                                          (NP_NNP 'Baltimore')  )
                                   ( PP
                                          (TO 'to' )
                                          ( NP
                                                 (NP_NNP 'Seattle' ))
                                                 ( NP
                                                        ( NP
                                                               (DT 'that' )
                                                               (NN 'stop') )
                                                        ( PP
                                                               (IN 'in' )
                                                               (NP_NNP 'Minneapolis')))))
              (PUNC '.') ) ))

我试图根据递归/缩进的次数来考虑一种方法,但没有取得太大的成功。

【问题讨论】:

    标签: python recursion tree nlp


    【解决方案1】:

    在每个终端节点(叶子)上,您正在为所有父母打印)s;你应该只为连续的右侧父母这样做。

    我建议将parents 重命名为depth 并添加一个right_depth 参数。

    编辑:在玩了一会儿之后,我决定最好将它委托给树:

    class Node:
        INDENT = "    "
    
        __slots__ = ["lhs", "word_label", "left_child", "right_child"]
    
        def __init__(self, lhs, *args):
            self.lhs = lhs
            num_args = len(args)
            if num_args == 1:
                self.word_label  = args[0]
                self.left_child  = None
                self.right_child = None
            elif num_args == 2:
                self.word_label  = None
                self.left_child  = args[0]
                self.right_child = args[1]
            else:
                raise ValueError("should have one arg (word_label: str) or two args (left: Node and right: Node)")
    
        def is_terminal(self):
            return self.word_label is not None
    
        def tree_str(self, depth=0, indent=None):
            if indent is None:
                indent = self.INDENT
            if self.is_terminal():
                return "\n{}({} '{}' )".format(
                    indent * depth,
                    self.lhs,
                    self.word_label
                )
            else:
                return "\n{}( {}{}{} )".format(
                    indent * depth,
                    self.lhs,
                    self.left_child .tree_str(depth + 1, indent),
                    self.right_child.tree_str(depth + 1, indent)
                )
    
        def __str__(self):
            return self.tree_str()
    

    然后是一些语法助手,

    def make_leaf_type(name):
        def fn(x):
            return Node(name, x)
        fn.__name__ = name
        return fn
    
    for leaf_type in ("VB", "DT", "NNS", "IN", "NP_NNP", "TO", "NN", "PUNC"):
        locals()[leaf_type] = make_leaf_type(leaf_type)
    
    def make_node_type(name):
        def fn(l, r):
            return Node(name, l, r)
        fn.__name__ = name
        return fn
    
    for node_type in ("TOP", "S_VP", "NP", "PP"):
        locals()[node_type] = make_node_type(node_type)
    

    这样我就可以创建树了,

    tree = \
        TOP(
            S_VP(
                VB('List'),
                NP(
                    NP(
                        DT('the'),
                        NNS('flights')
                    ),
                    PP(
                        PP(
                            IN('from'),
                            NP_NNP('Baltimore')
                        ),
                        PP(
                            TO('to'),
                            NP(
                                NP_NNP('Seattle'),
                                NP(
                                    NP(
                                        DT('that'),
                                        NN('stop')
                                    ),
                                    PP(
                                        IN('in'),
                                        NP_NNP('Minneapolis')
                                    )
                                )
                            )
                        )
                    )
                )
            ),
            PUNC('.')
        )
    

    然后打印出来

    >>> print(tree)
    ( TOP
        ( S_VP
            (VB 'List' )
            ( NP
                ( NP
                    (DT 'the' )
                    (NNS 'flights' ) )
                ( PP
                    ( PP
                        (IN 'from' )
                        (NP_NNP 'Baltimore' ) )
                    ( PP
                        (TO 'to' )
                        ( NP
                            (NP_NNP 'Seattle' )
                            ( NP
                                ( NP
                                    (DT 'that' )
                                    (NN 'stop' ) )
                                ( PP
                                    (IN 'in' )
                                    (NP_NNP 'Minneapolis' ) ) ) ) ) ) ) )
        (PUNC '.' ) )
    

    我认为实际上正是我们想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-05
      • 2015-11-04
      相关资源
      最近更新 更多