我有一个列表,例如[1,2,3,4,3,2,4]
。
我想输出每个元素一次,例如[1,2,3,4]
。
我该如何在Haskell中做到这一点?
答案 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]