我正在阅读Martin O.的Scala编程书。有一个例子可以删除重复项让我很困惑:
def removeDuplicates[A](xs: List[A]): List[A] = {
if (xs.isEmpty) xs
else
xs.head :: removeDuplicates(
xs.tail filter (x => x != xs.head)
)
}
println(removeDuplicates[String](List("a", "a", "b", "a", "c")))
给了我:
List(a,b,c)
我知道.head
将为您提供列表的第一个元素,而.tail
会为您提供列表的其余部分。我可以理解xs.tail filter (x => x != xs.head)
将返回一个列表,其中包含与头部不相等的元素。
我的Google搜索会将我引导至this cons
运营商但是,我仍然很难将Martin的话语映射到此示例中。任何人都可以帮我理解这个::
在这个函数中是如何工作的?
答案 0 :(得分:1)
Scala的一个特点是以:
(冒号)结尾的运算符是右关联的,它们被调度到右边的对象,参数在左边。例如:a :: list
(中缀表示法)相当于list.::(a)
(方法表示法)。
查看::
(cons)的文档。它从元素和另一个列表构造链接列表。请注意,a :: b :: c :: Nil
相当于List(a, b, c)
,但请注意,构造是从右到左发生的,Nil.::(c).::(b).::(a)
。
您给出的示例使用递归,该递归基于基本案例和归纳案例。基本案例表明空列表没有重复项。归纳案例说,假设你有一个removeDuplicates
方法可以删除列表中的所有重复项,你可以通过在开头添加一个值来构造一个新的(有时更大的)无重复列表,只要你首先从列表的其余部分中删除该值。
答案 1 :(得分:0)
这是函数式编程中非常常见的模式。
意识到removeDuplicates
计算到一个列表,其中cons运算符在其右侧。最终结果是一个列表,它的尾部不包含它的头部。
每次递增,我们将剩余列表的头部添加到我们使用cons运算符构建的新列表中。我们看看当前头部是否存在于列表的其余部分,并将其过滤掉。
查找map
方法是什么。如果你了解它的工作原理,那就应该点击。它们不完全相同,但它涉及使用cons运算符构建列表。