我在数据库中看到了一个与我的问题类似的问题,但这与我对代码的怀疑无关。我正在看下面的代码,因为我听不懂res.last.head!=h
而陷入困境。我搜索了Scala的文档,但找不到_.last.head
。
def _pack(res: List[List[A]], rem: List[A]):List[List[A]] = rem match {
case Nil => res
case h::tail if (res.isEmpty || res.last.head != h) => _pack(res:::List(List(h)), tail)
case h::tail => _pack(res.init:::List(res.last:::List(h)), tail)
}
_pack(List(),l)
}
println(pack(List(1,1,2,3,3)))
答案 0 :(得分:2)
我不确定您在那里遇到什么麻烦。您可以在List[A]
ScalaDoc中找到它们。
List[A]
是一个集合,内部存储为单个链接列表,每个节点(Cons
)的head
类型为A
,tail
输入List[A]
。
List[A].last
只是返回名称中所建议的列表中的最后一个元素(注意:这效率很低,因为它需要从头开始遍历整个列表)。现在,由于res
的类型为List[List[A]]
,因此res.last
的类型为List[A]
。 List[A].head
是列表中的第一个元素。
总结res.last.head
是列表List
中存储的最后res
的第一个元素。
为什么有两个带有
h::tail
的case语句。
您需要详细了解Pattern matching in Scala,尤其是有关“后卫”的知识。 match
/ case
中的代码可以重写为:
if (rem == Nil)
res // first case
else {
val h = rem.head
val tail = rem.tail
if (res.isEmpty || res.last.head != h)
_pack(res:::List(List(h)), tail) // second case
else
_pack(res.init:::List(res.last:::List(h)), tail) // last case
}
换句话说,代码首先检查rem
是否已经为空,如果为true,则退出。如果rem
不为空,我们取其head
(h
),现在我们可以选择:h
是否匹配列表中的前一个元素。 if
是第一种情况的守护者,没有if
的最后一种情况充当else
分支。