使用模式匹配来查找列表的最后一个元素

13
我正在尝试使用模式匹配在Scala中查找列表的最后一个元素。 我尝试了以下代码:
def last[A](list: List[A]):A = list match {
 case head :: Nil => head
 case head :: tail => last(tail)
 case _ => Nil
 }

最后一种情况,即case _ => Nil引发了类型不匹配的错误(找到Nil.type需要A)。
我知道可以使用其他方法解决此问题,但仅使用模式匹配是否有解决方法?
由于列表是泛型类型,因此我无法将Nil替换为只能在运行时确定的类型A的默认值。
删除这一行:case _ => Nil显然可以工作,但会出现警告,如果参数为Nil则会失败。
那么,如何处理这种情况下的Nil参数?
3个回答

45
你可以使用:+进行模式匹配。
def last[A](list: List[A]) = list match {
  case init :+ last => Some(last)
  case _ => None
}

很好。当然,也要是尾递归的。在我看来,这应该成为正确的答案。 - AmigoNico
有没有类似的提取器只针对最后一个元素?也就是说,“_:+ last”不适用于单个元素列表,例如“List(1)”。 - ComFreek
1
@ComFreek val _ :+ last = List(1) 对我来说是有效的。 - Jasper-M
可以有人解释一下,:+ last 如何成为类型为 A 的值吗?根据这个例子,我的期望是 List[A] - Sergii
@Sergii 这只是一个自定义提取器,没有任何神奇的事情发生。 - Jasper-M

4

由于您不确定列表是否包含任何对象,因此应以一般方式处理此类情况。我建议按照以下方式在您的last方法中返回选项类型:

def last[A](list: List[A]): Option[A] = list match {
    case head :: Nil => Some(head)
    case head :: tail => last(tail)
    case _ => None
}

然后在您的代码中,您可以使用类似于monad的接口来处理结果。您可以使用map并在提供的函数中处理数据,或者在确保列表不为空的情况下,可以使用选项中的get方法。


4

使用 Option[T] 来返回结果,如果有元素则返回 Some(lastElement),否则返回 Option.empty

例如:

  def last[A](list: List[A]): Option[A] = list match {
    case head :: Nil => Option(head)
    case head :: tail => last(tail)
    case _ => Option.empty
  }

  it("returns last element") {

    assert(last(List("apple")) == Some("apple"))
    assert(last(List("apple", "mango")) == Some("mango"))
    assert(last(List()) == Option.empty)
    assert(last(List()) == None)

  }

如何访问Option[T]

last(List("In absentia", "deadwind")) match {
  case Some(lastValue) => println(s"Yayy there was lastValue = ${lastValue}") //prints Yayy there was lastValue = deadwind
  case None => println("Oops list was empty")
}

last(List()) match {
  case Some(lastValue) => println(s"Yayy there was lastValue = ${lastValue}")
  case None => println("Oops list was empty") //prints Oops list was empty
}

// or using map
last(List("In absentia", "deadwind")).map(lastValue => print(s"lastValue is ${lastValue}"))

有没有办法在这里指定类似于 Java 中的“Null”(对于泛型类型),以便我们可以避免使用 Option? - Shashank
不建议这样做,因为这个想法是要消除“null”的概念。最后一个元素可以是“某个值”或“空”。您是否在处理返回的“Option”值时遇到任何问题?使用“returnedValue match {}”来处理返回的最后一个值。 - prayagupa
2
Shashank,你可能只在极少数情况下看到这种情况,因为它会对性能产生巨大影响,但这不是 Scala 的惯用方式。请注意,在这种情况下,您必须将 A 约束为 AnyRef,即 last[A <: AnyRef] - AmigoNico
@AmigoNico:如果我们这样想,那么这个确实有道理。谢谢。 - Shashank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接