我是Scala的新手,我正在学习关于集合的模式匹配,以便编写一个简单的逻辑来查找最后一个元素。这是我的第一次尝试:
@scala.concurrent.tailrec
def penultimate[A](elems: List[A]) = elems match {
case Nil => None
case first :: second :: Nil => Some(first)
case head :: tail => penultimate(tail)
}
这够好吗?我读到了关于尾递归的信息,并且我的方法是尾递归的!
但是,对于以下情况并且我期望Some(1):
,它失败了penultimate[Int](List(1)) // This should give me Some(1)
我还能做些什么吗?我可以使用Scala集合库中的反向方法,并使其成为一个单行,但我想远离使用它。
有更好的方法吗?
答案 0 :(得分:1)
如果您修复了这两个简单的编译错误,您的代码似乎可以正常工作。编写此方法的另一种方法是:
def penultimate[A](elems: List[A]) = elems match {
case _ :+ elem :+ _ => Some(elem)
case elem +: Nil => Some(elem) // strange extra requirement
case _ => None
}
:+
将Seq
解构为(1)除最后一个元素之外的所有元素的列表,以及(2)最后一个元素。与::
或更为一般的+:
相似但反向。我本来可以写case init :+ elem :+ last
,但我不想给我不打算使用的模式部分命名。
答案 1 :(得分:0)
倒数第二位的要求是,列表中至少应包含2个元素。因此,在上面的“ penultimateInt”中应该抛出异常。
def penultimate[A](elems: List[A]) = {
val result = getSecondLast(elems)
if(result.isDefined) result.get else throw new Exception("list doesn't have
enough elementss")
}
@tailrec
private def getSecondLast[A](list: List[A], secondLast: Option[A] = None):
Option[A] = {
list match {
case secondLast :: _ :: Nil => Some(secondLast)
case _ :: tail => getSecondLast(tail, secondLast)
case _ => None
}
}
以上是递归方法。 使用可用方法的其他方式是: