递归构建Binary Tree逻辑错误,是否应从中间连词开始构建?
问题描述
给定基础文本:
text = "The user's Average Revenue Per User (ARPU) has experienced a significant decrease due to high decrement and they have been inactive in terms of outgoing voice calls, data usage, and SMS for a consecutive period of 5 days. or they are having handset"
文本中的连词为:
conjunctions = [and, and, or]
需要构建指定的二叉树,并编写了基于spaCy的Python代码(代码如下),目前代码逻辑存在错误,询问是否应该选取中间连词作为起点,递归构建该二叉树?
import spacy class Node: def __init__(self, value, left=None, right=None): self.value = value self.left = left self.right = right class Parser(object): def __init__(self, text=None): self.text = text pass def parse_left(self, conj_list, text): conj_index = cont_index_list[0][0] conj = str(conj_list[0][1]) left = text.split(conj)[0] self.text = f"{conj}".join(self.text.split(conj)[1:]) return left def parse_right(self, text, conj_list): # conj_index = cont_index_list[0][0] conj = str(conj_list[0][1]) conj_next = None try: conj_next = str(conj_list[1][1]) except: print("last conj") right = text.split(f" {conj} ")[0] self.text = f"{conj}".join(self.text.split(conj)[1:]) # right = right.split(conj_next) return right def recursion_tree(self, node, text, conj_list): # code for if the text len is empty then return the tree # if ndoe is none create a leaf node if node is None: n1 = Node(conj_list[0][1]) left = self.parse_left(conj_list, self.text) conj_list.pop(0) right = self.parse_right(self.text, conj_list) conj_list.pop(0) n1.left = left n1.right = right self.recursion_tree(n1, self.text, conj_list) else: n1 = Node(conj_list[0][1]) n1.left = node right = self.parse_right(self.text, conj_list) n1.right = right self.recursion_tree(n1, self.text, conj_list) if __name__ == '__main__': # Load the spaCy model nlp = spacy.load('en_core_web_sm') node = None text = "The user's Average Revenue Per User (ARPU) has experienced a significant decrease due to high decrement and they have been inactive in terms of outgoing voice calls, data usage, and SMS for a consecutive period of 5 days. or they are having handset" doc = nlp(text) # Extract conjunctions conjunctions = [token for token in doc if token.dep_ in {'cc', 'mark'} or token.pos_ == "CONJ"] conj_list = [] cont_index_list = [] for i in range(len(conjunctions)): print(i) conj_list.append((i, conjunctions[i])) cont_index_list.append((i, text.index(conjunctions[i].text))) p = Parser(text=text) p.recursion_tree(node, text, conj_list)
回答
是的,应该从中间连词(也就是第二个and)作为起点递归构建二叉树,核心原因是连词的语义优先级和文本的逻辑结构:
- 最内层逻辑:
outgoing voice calls, data usage, and SMS里的第二个and连接的是三个并列的通信行为,属于最细粒度的并列单元 - 中间层逻辑:第一个
and连接的是“ARPU大幅下降”和“连续5天无通信行为”两个并列的用户状态 - 最外层逻辑:
or连接的是“用户状态异常”和“终端问题”两个并列的原因分支
递归构建的正确逻辑应该是从最底层的连词开始,逐步向上合并:
- 以第二个
and为根节点,左子节点为data usage,右子节点为SMS,将该子树替换原文本中data usage and SMS的部分,得到outgoing voice calls, [and子树]的片段 - 把
outgoing voice calls和上述子树整合,作为“连续5天无通信行为”的具体内容 - 以第一个
and为根节点,左子节点为“ARPU大幅下降”的文本,右子节点为第二步得到的子树 - 以最外层的
or为根节点,左子节点为第三步的子树,右子节点为they are having handset
另外你当前代码的几个明显问题需要修正:
cont_index_list是全局变量,Parser类直接调用会报错,应改为实例属性传入或管理- 缺失递归终止条件,会引发无限递归
- 直接用
split分割文本会忽略上下文语义,应该结合spaCy的依存分析结果,定位每个连词真正连接的两个成分,而非简单切割字符串
内容的提问来源于stack exchange,提问作者aziz shaw
相关产品推荐
相关产品推荐

