【问题标题】:Findig the 2nd last item in the list, please explain this solution查找列表中的倒数第二项,请解释此解决方案
【发布时间】:2011-09-26 06:40:14
【问题描述】:
// 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项,然后取第1项获得最后2项,困惑!

【问题讨论】:

    标签: list scala recursion functional-programming pattern-matching


    【解决方案1】:

    理解模式匹配的关键是要意识到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,因为这是唯一与其他两个条目不匹配的可能性。)

    【讨论】:

    • x :: y 将匹配 x 后跟 任何列表 y,即零个或多个元素。
    • @larsmans - 这就是我的意思,但整个Nil 是一个项目,事情并不明显(或者,根据你的观点,不正确)。我会修正我的措辞。
    • 您可能会更清楚地说明,模式匹配中的小写标识符类似于val 声明,因为这些标识符是在匹配范围内创建的,并从匹配中提取分配值。确保 小写 部分,并将其与大写 Nil 进行对比,与之进行比较。
    • 在哪里可以找到语言参考中的运算符 ::?
    • List 是抽象的,有两个子类:"::" 和 Nil。这是前者的文档:scala-lang.org/api/current/…
    【解决方案2】:

    larsmans 和 Rex 已经回答了您的问题,但请参阅第 9 章了解更多关于 '::' http://www.scala-lang.org/docu/files/ScalaByExample.pdf

    【讨论】:

      【解决方案3】:

      第一行表示如果 h 后面跟着另一个元素和一个 Nil 指针(在列表的末尾),则将返回任何列表元素 h。 h 后面的实际元素并不重要,这就是为什么你使用 _ 来指定有一个元素但你不关心它的值。

      如果第一种情况不匹配,如果列表有一个头元素和至少一个元素的尾,则第二种情况将调用递归。

      最后,您可以摆脱仅包含单个元素的列表。再一次,您不必关心元素值的实际值。

      【讨论】:

        【解决方案4】:

        A 是一个类型变量,这意味着该函数被泛型定义为任何类型A

        h 受模式匹配的约束:第一个case 表示,如果恰好有两个元素,则调用第一个h 并返回它。

        似乎没有'检查列表中的 2 个项目

        有:h :: _ :: Nil 的意思是“一个元素 h,后跟任何元素,然后再没有其他元素。” Nil 不是元素,它是列表的结尾。

        然后取第 1 项,得到倒数第 2 项

        取第一个双元素列表意味着取倒数第二个。如果列表的元素少于或多于两个,则适用其他两种情况。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-11
          • 2018-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多