如何仅从列表中获取唯一元素?

时间:2019-12-17 10:58:09

标签: list haskell functional-programming unique

我有一个列表,例如[1,2,3,4,3,2,4]。 我想输出每个元素一次,例如[1,2,3,4]。 我该如何在Haskell中做到这一点?

4 个答案:

答案 0 :(得分:12)

您可以使用this source作为唯一性过滤器。但是,由于它不使用像哈希集这样的数据结构,因此将需要 O(n 2

例如:

Prelude Data.List> nub [1,2,3,4,3,2,4]
[1,2,3,4]

如果元素的类型是nub :: Eq a => [a] -> [a]的成员,则可以使用Hashable typeclass O(n log n):

Prelude ClassyPrelude> hashNub [1,2,3,4,3,2,4]
[1,2,3,4]

答案 1 :(得分:10)

您可以使用Data.set对集合进行操作:

import qualified Data.Set as Set
lst = [1,2,3,4,1,2,3]
y =  Set.fromList lst

输出为:

y
=> fromList [1,2,3,4]

答案 2 :(得分:5)

确实有一个nub函数。但是,它的复杂度为O(n ^ 2),不是很好。如果是数字(或任何Ord类型),则可以像这样创建自己的unique函数:

unique :: Ord a => [a] -> [a]
unique = map head . group . sort

您需要导入Data.List。 它是这样的:

sort [1,2,3,1,2] -> [1,1,2,2,3]        -- to order the elements
group [1,1,2,2,3] -> [[1,1],[2,2],[3]] -- to group equal ones
map head [[1,1],[2,2],[3]] -> [1,2,3]  -- to take first of groups

这具有O(n log n)的复杂度,这是更好的方法。

答案 3 :(得分:2)

基本上,由于Haskell列表中的sort处理非常快(最佳情况O(n)最坏情况O(nlogn),我们可以先使用排序,然后再折叠以获得有效的解决方案,并获得排序的其他效果结果,如果那将是有益的。

以下代码用于最少的cons操作;

Prelude Data.List
λ> :{
λ| foldr (\e rs -> case rs of
λ|                 []     -> [e]
λ|                 (x:xs) -> if x == e then rs else e:rs) [] $ sort [8,8,4,3,2,3,3,2,1,8,3,5]
λ| :}
[1,2,3,4,5,8]

以下是@Joseph Sible-Reinstate Monica指出的增强懒惰。

Prelude Data.List
λ> :{
λ| foldr (\e rs -> e : case rs of
λ|                 []     -> []
λ|                 (x:xs) -> if x == e then xs else rs) [] $ sort [8,8,4,3,2,3,3,2,1,8,3,5]
λ| :}
[1,2,3,4,5,8]