Scala使用::删除重复数据删除

时间:2015-07-01 02:32:49

标签: scala

我正在阅读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的话语映射到此示例中。任何人都可以帮我理解这个::在这个函数中是如何工作的?

2 个答案:

答案 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运算符构建列表。