【发布时间】:2019-12-17 10:58:09
【问题描述】:
我有一个列表,比如[1,2,3,4,3,2,4]。
我想将每个元素输出一次,例如[1,2,3,4]。
我怎样才能在 Haskell 中做到这一点?
【问题讨论】:
-
谢谢,完全忘记了。对于这种情况就足够了,因为我没有处理很多日期
标签: list haskell functional-programming unique
我有一个列表,比如[1,2,3,4,3,2,4]。
我想将每个元素输出一次,例如[1,2,3,4]。
我怎样才能在 Haskell 中做到这一点?
【问题讨论】:
标签: list haskell functional-programming unique
您可以使用nub :: Eq a => [a] -> [a] 作为uniqness 过滤器。然而,它需要 O(n2),因为它不使用像哈希集这样的数据结构。
例如:
Prelude Data.List> nub [1,2,3,4,3,2,4]
[1,2,3,4]
如果元素属于Hashable typeclass 的成员类型,您可以使用例如hashNub :: (Eq a, Hashable a) => [a] -> [a] 在O(n log n) 中执行唯一性过滤器: p>
Prelude ClassyPrelude> hashNub [1,2,3,4,3,2,4]
[1,2,3,4]
【讨论】:
hashNub,也有来自containers包的nubOrd and nubInt,它们分别使用Set和IntSet来实现相同的O(n log n) 复杂性。 (看起来hashNub 需要classy-prelude 或witherable 包。)
nubOrdOn 和nubIntOn,让您可以对列表中的元素进行分类,并且只取每个类别中的第一个。
您可以使用 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]
【讨论】:
有一个 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) 的复杂度,这是一种更好的方式。
【讨论】:
nubOrd?
基本上,由于 Haskell 列表中的 sorting 非常快(最佳情况 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]
【讨论】: