找到列表中的倒数第二项,请解释一下这个解决方案

发布于 2024-11-17 23:32:20 字数 509 浏览 0 评论 0原文

// 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 个项目,然后取出第一个项目来获取最后第二个项目,很困惑!

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

Can someone comment what this is doing line by line?

Is the [A] a generic like in c# we would do ?

h doesn't seem to be defined?

I think the major part of the algo is the recursive call:

case _ :: tail     => penultimateRecursive(tail)

There doesnt' seem to be a check for 2 items in the list, and then taking the 1st item to get the 2nd last, confused!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

挽袖吟 2024-11-24 23:32:21

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

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

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

The first line means that any list element h will be returned if h is followed by another one and a Nil pointer (at the end of the list). The actual element following to h is not important, that's why you use _ to specify that there is an element but you don't care about its value.

If the first case does not match, the second case will invoke recursion if the list has a head element and a tail of at least one element.

Lastly you bail out on lists consisting only a single element. Once again, you don't have to care about the actual value of the elements value.

情仇皆在手 2024-11-24 23:32:20

理解模式匹配的关键是要认识到 x :: y匹配包含单个项目 x 和其余项目的列表列表y(可能只是Nil,也可能是许多元素),而_意味着“这里需要有一些东西,但我们不会费心命名它”。 (并且匹配按顺序出现,并且列表以 Nil 结尾。)

您是对的,[A] 是泛型类型。

所以,第一行:

case h :: _ :: Nil => h

说,如果我们的列表看起来像(概念上) Node(h) ->节点(无论如何)-> Nil,然后我们返回h。这正是一个包含两个元素的列表,其中第一个项目被选中。请注意,Nil 确实匹配列表的任意尾部;它仅匹配列表末尾的项Nil。这是因为 Scala 使用一条规则来区分这两者:小写变量被视为通配符,需要填充适当的值,而大写变量则被视为常量来匹配。 (如果必须匹配小写名称,则可以用反引号将其括起来。)

好的,现在假设它不是一个二元素列表。然后,如果它不为空,它将匹配,

case _ :: tail => penultimateRecursive(tail)

因此如果我们没有两个元素列表,我们会丢弃第一个项目并重试。最后,如果我们以某种方式从未得到一个二元素列表,那么我们就

case _ => throw new NoSuchElementException

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

The keys to understanding the pattern match are to realize that x :: y will only match a list with a single item x followed by the rest of the list y (which could be just Nil, or could be many elements), and that _ means "there needs to be something here, but we won't bother naming it". (And that the matches occur in order, and that lists end with Nil.)

You're correct that [A] is a generic type.

So, the first line:

case h :: _ :: Nil => h

says, if our list looks like (conceptually) Node(h) -> Node(whatever) -> Nil, then we return h. This is exactly a two-element list with the first item selected. Note that Nil does not match any arbitrary tail of the list; it matches only the end-of-list item Nil. This is because of a rule that Scala uses to distinguish the two: lower case variables are treated as wildcards that are to have the appropriate value filled in, while upper case variables are treated as constants to match. (If you must match a lower-case name, you can if surround it by backticks.)

Okay, now suppose it's not a two-element list. Then if it's not empty, it will match

case _ :: tail => penultimateRecursive(tail)

so if we haven't got a two-element list, we throw away the first item and try again. Finally, if we somehow never ended up with a two-element list, we get to

case _ => throw new NoSuchElementException

and we're done. (This could also be case Nil, actually, since this is the only possibility that doesn't match the other two entries.)

失眠症患者 2024-11-24 23:32:20

A 是一个类型变量,这意味着该函数是为任何类型 A 通用定义的。

h 由模式匹配绑定:第一个 case 声明,如果正好有两个元素,则调用第一个 h 并返回它。

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

存在: h :: _ :: Nil 表示“一个元素 h,后跟任何元素,后跟不再有任何元素。” Nil 不是一个元素,它是列表的末尾。

然后从第一项获取最后第二项

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

A is a type variable, meaning the function is defined generically for any type A.

h is bound by the pattern matching: the first case states, if there are exactly two elements, then call the first h and return it.

There doesnt' seem to be a check for 2 items in the list

There is: h :: _ :: Nil means "an element h, followed by any element, followed by no more elements." Nil isn't an element, it's the end of the list.

and then taking the 1st item to get the 2nd last

Taking the first of a two-element list means taking the penultimate. If the list has fewer or more elements than two, the other two cases apply.

ゝ杯具 2024-11-24 23:32:20

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

larsmans and Rex have covered your questions, but see Chapter 9 for more details on '::' http://www.scala-lang.org/docu/files/ScalaByExample.pdf

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文