// 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/