Haskell从列表中删除重复项

时间:2015-06-30 23:47:08

标签: haskell

我是Haskell的新手,我正在尝试以下代码从列表中删除重复项。但它似乎不起作用。

compress []     = []
compress (x:xs) = x : (compress $ dropWhile (== x) xs)

我尝试了一些搜索,所有建议都使用了foldr / map.head。是否有基本结构的实现?

3 个答案:

答案 0 :(得分:4)

我认为您在代码中提到的问题是您当前的实现只会删除相邻的重复项。正如它在评论中发布的那样,内置函数 nub 将消除每个重复项,即使它不相邻,也只保留第一次出现的任何元素。但是既然你问过如何用基本结构实现这样的函数,那怎么样呢?

wingArea

我向你介绍的唯一新功能是 filter ,它根据谓词过滤列表(在这种情况下,去除列表其余部分中存在的每个元素)当前元素)。

我希望这会有所帮助。

答案 1 :(得分:1)

首先,不要简单地在一个问题中陈述“不起作用”。这使读者可以检查它是编译时错误,运行时错误还是错误结果。

在这种情况下,我猜这是一个错误的结果,如下:

> compress [1,1,2,2,3,3,1]
[1,2,3,1]

您的代码存在的问题是它只删除了连续的重复项。第一对1被压缩,但最后一个1因此而被删除。

如果可以,请提前对列表进行排序。这将使相等的元素关闭,然后compress做正确的工作。当然,输出的顺序不同。如果需要,还有一些方法可以保持订单(从zip [0..] xs开始,然后排序,然后......)。

如果你不能排序,那么确实没有实际的方法来定义比较,只有一个相等,那么使用nub。请注意,这比排序和效率低得多。压缩。这种性能损失是固有的:没有比较器,你只能使用低效的二次算法。

答案 2 :(得分:0)

foldr 地图是非常基本的FP构造。然而,它们非常普遍,我发现它们有点令人费解,很长一段时间都无法理解。 Tony Morris' talk Explain List Folds to Yourself给了我很多帮助。

在您的情况下,现有的列表函数,如 filter ::(a - > Bool) - > [a] - > [a] 可以使用带有副本的谓词代替 dropWhile