次のコードを使用して、Python でツリー オブジェクトを作成しました。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re,sys,codecs
neg_markers_en=[u'not',u"napt",u'no',u'nobody',u'none',u'never']
class Node:
def __init__(self,name=None,parent=None,sentence_number=0):
self.name=name
self.next=list()
self.parent=parent
self.depth=0
self.n_of_neg=0
self.subordinate=None
self.foo=None
def print_node(self):
print self.name,'contains',[(x.name,x.depth,x.foo) for x in self.next]
for x in self.next:
x.print_node()
def get_negation(self):
for x in self.next:
if x.n_of_neg!=0:
print unicode(x.depth)+u' |||',
try:
x.look_for_parent_vp()
except: print 'not in a VP',
try:
x.look_for_parent_sent()
except: print '***'
x.get_negation()
def look_for_parent_vp(self):
if self.parent.name=='VP':
self.parent.print_nont()
else:
self.parent.look_for_parent_vp()
def look_for_parent_sent(self):
if self.parent.name=='S' or self.parent.name=='SBAR':
#This is to send out to a text file, along with what it covers
print '||| '+ self.parent.name,
try:
self.parent.check_subordinate()
self.parent.print_nont()
print '\n'
except:
print u'no sub |||',
self.parent.print_nont()
print '\n'
elif self.parent=='None': print 'root |||'
else:
self.parent.look_for_parent_sent()
def print_nont(self):
for x in self.next:
if x.next==[]:
print unicode(x.name),
else: x.print_nont()
def mark_subordinate(self):
for x in self.next:
if x.name=='SBAR':
x.subordinate='sub'
else: x.subordinate='main'
x.mark_subordinate()
def check_subordinate(self):
if self.subordinate=='sub':
print u'sub |||',
else:
self.parent.check_subordinate()
def create_tree(tree):
#replace "n't" with 'napt' so to avoid errors in splitting
tree=tree.replace("n't",'napt')
lista=filter(lambda x: x!=' ',re.findall(r"\w+|\W",tree))
start_node=Node(name='*NULL*')
current_node=start_node
for i in range(len(lista)-1):
if lista[i]=='(':
next_node=Node()
next_node.parent=current_node
next_node.depth=current_node.depth+1
current_node.next.append(next_node)
current_node=next_node
elif lista[i]==')':
current_node=current_node.parent
else:
if lista[i-1]=='(' or lista[i-1]==')':
current_node.name=lista[i]
else:
next_node=Node()
next_node.name=lista[i]
next_node.parent=current_node
#marks the depth of the node
next_node.depth=current_node.depth+1
if lista[i] in neg_markers_en:
current_node.n_of_neg+=1
current_node.next.append(next_node)
return start_node
これで、すべてのノードがリンクされ、親ノードの子ノードがリストに追加され、これらの子ノードのそれぞれがインスタンスの親を介して親に参照されます。次の問題があります。名前が 'S' または 'SBAR' である各ノード ( と呼びましょうnode_to_check
) について、その子ノードの名前が 'S' または 'SBAR' であるかどうかを確認する必要があります。そうでない.foo
場合は、の属性をnode_to_check
「atom」に変換します。
私は次のようなことを考えていました:
def find_node_to_check(self):
for next in self.next:
if next.name == 'S' or next.name == 'SBAR':
is_present = check_children(next)
if is_present == 'no':
find_node_to_check(next)
else:
self.foo = 'atom'
def check_children(self):
for next in self.next:
# is this way of returning correct?
if next.name == 'S' or next.name == 'SBAR':
return 'no'
else:
check_sents(next)
return 'yes'
これまでに書いたコードも質問に含めました。ツリー構造は関数 create_tree(tree); で作成されます。入力ツリーは、スタンフォード パーサーのブラケット表記です。