【发布时间】:2017-03-02 20:28:50
【问题描述】:
我正在尝试以尾递归的方式创建一个横切具有树状结构的对象的函数,但到目前为止我无法编写代码来实现它。
我的树状对象是:
case class Node(lex: String,
position: Int,
posTag: String,
var dependency: Int = -1,
var left: Vector[Node],
var right: Vector[Node])
版本 1,尾递归(不工作)
到目前为止,我已经尝试过最简单的形式:
def matchNodes(goldSentence: LabeledSentence): Int = {
def condition(n: Node): Boolean = ???
@tailrec
def match0(acc: Int, n: Seq[Node]): Int =
(n: @switch) match {
case head :: tail => {
if (condition(head)) {
match0(acc + 1, tail)
} else {
acc
}
}
case _ => acc
}
match0(0, left) + match0(0, right)
}
上面的代码是tailrec,但不是遍历整棵树,只是第一层。
版本 2,尾递归(不工作)
其他方式是:
def matchNodes(goldSentence: LabeledSentence): Int = {
@inline def condition(n: Node): Boolean = ???
def sumAcc(nodes: Vector[Node]): Vector[Node] = nodes match {
case head +: tail => sumAcc(head.left ++ head.right ++ tail)
case _ => nodes
}
@tailrec
def match0(acc: Int, n: Seq[Node]): Int =
(n: @switch) match {
case head :: tail => {
if (condition(head)) {
match0(acc + 1, tail)
} else {
acc
}
}
case _ => acc
}
val flatTree = sumAcc(right ++ left)
match0(0, flatTree)
}
这里我尝试将所有节点扁平化为一个Vector[Node],但由于某种原因,处理树后的预期结果不正确。
版本 3,无尾递归(工作)
我尝试的最后一个代码不是尾递归的,但它是唯一计算正确结果的代码:
def matchNodes(goldSentence: LabeledSentence): Int = {
var correctRoots = 0
val position:Int = this.position
val dep:Int = dependency
val tag = goldSentence.tags(position)
if (goldSentence.dep(position) == dep || Constants.punctuationTags.contains(tag))
correctRoots += 1
if (right.nonEmpty)
for (r <- right)
correctRoots += r.matchNodes(goldSentence)
if (left.nonEmpty)
for (l <- left)
correctRoots += l.matchNodes(goldSentence)
correctRoots
}
有没有办法让这个函数尾递归?
【问题讨论】:
-
你能提供你输入的样本数据吗?
-
我已经更新了
node类的成员。输入是关于句子的信息。句子中的每个单词都有一个词汇值、依赖值和一个 PosTag。这是你想要的吗? -
我想要一个你想要遍历的样本
Seq[Node]。
标签: scala recursion traversal tail-recursion