主要是识别孩子。我将尝试解释我的代码:
class TreeNode:
def __init__(self, string):
self.im_leaf = string[0] != '('
self.children = []
if not self.im_leaf:
first_space_index = string.index(" ")
self.label = string[1:first_space_index]
string = string[first_space_index + 1 : -1] #rest of the tree
for node in self.split(string):
self.children.append(TreeNode(node))
else:
self.label = string
self.text = self.calculate_text()
def calculate_text(self):
if self.im_leaf:
return self.label + ' '
text = ''
for node in self.children:
text += node.calculate_text()
return text
def split(self, string):
splitted = []
pair_parenthesis = 0
index = 0
for i in range(len(string)):
char = string[i]
if char == '(':
pair_parenthesis += 1
elif char == ')':
pair_parenthesis -= 1
if pair_parenthesis == 0:
new_node = string[index:i+1]
if new_node[0] == ' ':
new_node = new_node[1:]
splitted.append(new_node)
index = i + 1
if len(splitted) == 0:
splitted = [string]
return splitted
首先,在__init__ 中,我知道给定的字符串是否描述了由第一个字符确定的叶子,如果它不是“开括号”('('),那么当前字符串描述的是叶子,例如"cow" 或 Where;与 "(NP (DT the) (NN cow))" 等“非叶字符串”不同。
如果string 描述了一片叶子,那么label = string,否则label 是第一个括号(始终位于第一个位置)和第一个空格之间的子字符串。此外,在后一种情况下,需要识别不同的分支,这可以通过 split 方法完成。然后,递归识别children。
split 方法通过计算开括号和闭括号来识别分支。请注意"(WHADVP (WRB Where)) (VBZ is) (NP (DT the) (NN cow))" 中的第一个分支是(WHADVP (WRB Where)),即代码中开括号的数量第一次等于闭括号的数量(这个差异是存储在pair_parenthesis 中的)。第二个和第三个分支也是如此。如果一个分支只有一个子分支,例如"(WRB Where)",则该方法将使用字符串"Where" 调用,在这种情况下,它会返回"[Where]"。
最后,text 被分配给calculate_text 方法,它基本上通过树搜索叶子进行递归调用。如果节点是叶子,则将其标签添加到text。
现在进行一些测试:
test_tree = TreeNode('(SBARQ (WHADVP (WRB Where)) (VBZ is) (NP (DT the) (NN cow)))')
print(test_tree.label)
#SBARQ
print(test_tree.text)
#Where is the cow
print(test_tree.children[0].text) #text from the "WHADVP" node
#Where
如果有什么不清楚的地方请告诉我。