list - 在列表中找到倒数第二个项目,请解释此解决方案

标签 list scala recursion functional-programming pattern-matching

// But pattern matching also makes it easy.
  def penultimateRecursive[A](ls: List[A]): A = ls match {
    case h :: _ :: Nil => h
    case _ :: tail     => penultimateRecursive(tail)
    case _             => throw new NoSuchElementException
  }

有人可以逐行评论这是做什么的吗?

[A]是否像我们将要在C#中那样使用泛型?

h似乎没有定义?

我认为算法的主要部分是递归调用:
case _ :: tail     => penultimateRecursive(tail)

似乎没有检查列表中的2个项目,然后拿第一个项目获得倒数第二个,很困惑!

最佳答案

理解模式匹配的关键是要认识到x :: y将只匹配具有单个项目x的列表,然后匹配列表的其余部分y(可以只是Nil,也可以是许多元素),并且_的意思是“存在需要在这里做些什么,但我们不会为它命名而烦恼”。 (并且匹配按顺序进行,并且列表以Nil结尾。)

您说对了,[A]是通用类型。

因此,第一行:

case h :: _ :: Nil => h

说,如果我们的列表在概念上看起来像Node(h) -> Node(whatever) -> Nil,那么我们返回h。这恰好是一个包含两个元素的列表,并且选择了第一个项目。注意Nil与列表的任意尾部都不匹配;它仅匹配列表结尾项Nil。这是由于Scala用来区分两者的规则:将小写变量视为将填充适当值的通配符,而将大写变量视为要匹配的常量。 (如果必须匹配小写名称,则可以用反引号将其括起来。)

好吧,现在假设它不是一个包含两个元素的列表。然后,如果不为空,它将匹配
case _ :: tail => penultimateRecursive(tail)

因此,如果我们没有包含两个元素的列表,我们将丢弃第一项,然后重试。最后,如果我们以某种方式从未以两个元素组成的列表结束,那么我们可以
case _ => throw new NoSuchElementException

我们完成了。 (实际上,这也可能是case Nil,因为这是唯一与其他两个条目不匹配的可能性。)

关于list - 在列表中找到倒数第二个项目,请解释此解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6540158/

相关文章:

python - 使用关联列表对象的函数迭代列表

scala - 为什么私有(private)构造函数在案例类中仍然可见?

scala - spark中的求和向量列

scala - 带有内部案例类的案例类的字符串列表

python - 避免 DP 的尾递归 python

java - 矩形的递归碰撞检测不太有效

python - 为什么我的 python 函数不返回我的任何条件,除了无?

python - 生成列表的所有可能组合, "itertools.combinations"遗漏了一些结果

ruby - 查找二叉树的叶子

python - 从列表中提取标题并创建一个带有并排标题的 DataFrame 以列出元素