使用模式匹配以递归方式在scala中查找列表的第n个元素

时间:2014-06-30 05:46:42

标签: list scala recursion pattern-matching

我在这里遇到了99个scala问题(http://aperiodic.net/phil/scala/s-99/p03.scala)的问题,我试图弄清楚它是如何工作的。我对Scala很新。我能够使用模式匹配和递归的类似解决方案完成此挑战,但是我没有考虑匹配中的列表。我的代码如下:

def nth[A](k: Int, l: List[A]): A = k match {
  case 0 => l.head
  case _ => nth(k-1, l.drop(1))
}

这似乎完成了这项工作。但是,如果列表为Nil,则不会检查错误。 99 scala问题提供的解决方案是:

def nthRecursive[A](n: Int, ls: List[A]): A = (n, ls) match {
  case (0, h :: _   ) => h
  case (n, _ :: tail) => nthRecursive(n - 1, tail)
  case (_, Nil      ) => throw new NoSuchElementException
}

我不明白的是

case(0, h:: _ )

case(n, _ :: tail)

作者在这做什么?我理解::将左侧的任何内容添加到右侧的开头,但我不确定究竟发生了什么。谁能开导我?

谢谢!

2 个答案:

答案 0 :(得分:2)

::运算符用于提取头部和列表的其余部分(尾部)。

下面:

case(0, h :: _ )

只有头部是相关的,所以尾部没有参考。

在这里:

case(n, _ :: tail)

只有尾部是相关的,所以头部没有得到参考。

您也可以使用:

case(0, head :: tail)
case(n, head :: tail)

(即给两个部分一个参考)并得到完全相同的结果。

答案 1 :(得分:1)

基本上,它是模式匹配表达式。这就是Scala模式匹配如此强大的原因,因此我们可以放弃一些像Java这样的重型访问者模式(在本主题之外)。

一个简单的例子:

case class User(name: String, age: Int)

def doStuff(user: User) = user match {
  case User(_, age) if age > 100 => println("Impossible!")
  case User(name, _) => println("hello " + name)
}

在这种情况下,_ :: tail只是意味着我想获得尾部的引用。