找到列表中的倒数第二项,请解释一下这个解决方案
// 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
第一行意味着如果 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.
理解模式匹配的关键是要认识到
x :: y
将仅匹配包含单个项目x
和其余项目的列表列表y
(可能只是Nil
,也可能是许多元素),而_
意味着“这里需要有一些东西,但我们不会费心命名它”。 (并且匹配按顺序出现,并且列表以Nil
结尾。)您是对的,
[A]
是泛型类型。所以,第一行:
说,如果我们的列表看起来像(概念上)
Node(h) ->节点(无论如何)-> Nil
,然后我们返回h
。这正是一个包含两个元素的列表,其中第一个项目被选中。请注意,Nil
确实不匹配列表的任意尾部;它仅匹配列表末尾的项Nil
。这是因为 Scala 使用一条规则来区分这两者:小写变量被视为通配符,需要填充适当的值,而大写变量则被视为常量来匹配。 (如果必须匹配小写名称,则可以用反引号将其括起来。)好的,现在假设它不是一个二元素列表。然后,如果它不为空,它将匹配,
因此如果我们没有两个元素列表,我们会丢弃第一个项目并重试。最后,如果我们以某种方式从未得到一个二元素列表,那么我们就
完成了。 (实际上,这也可能是 case Nil,因为这是唯一与其他两个条目不匹配的可能性。)
The keys to understanding the pattern match are to realize that
x :: y
will only match a list with a single itemx
followed by the rest of the listy
(which could be justNil
, 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 withNil
.)You're correct that
[A]
is a generic type.So, the first line:
says, if our list looks like (conceptually)
Node(h) -> Node(whatever) -> Nil
, then we returnh
. This is exactly a two-element list with the first item selected. Note thatNil
does not match any arbitrary tail of the list; it matches only the end-of-list itemNil
. 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
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
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.)A
是一个类型变量,这意味着该函数是为任何类型A
通用定义的。h
由模式匹配绑定:第一个case
声明,如果正好有两个元素,则调用第一个h
并返回它。存在:
h :: _ :: Nil
表示“一个元素h
,后跟任何元素,后跟不再有任何元素。”Nil
不是一个元素,它是列表的末尾。取二元素列表的第一个意味着取倒数第二个。如果列表的元素少于或多于两个,则应用其他两种情况。
A
is a type variable, meaning the function is defined generically for any typeA
.h
is bound by the pattern matching: the firstcase
states, if there are exactly two elements, then call the firsth
and return it.There is:
h :: _ :: Nil
means "an elementh
, followed by any element, followed by no more elements."Nil
isn't an element, it's the end of the list.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.
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