是否有一个Haskell函数接受一个列表并返回该列表中的重复/冗余元素列表?
我知道nub
和nubBy
函数,但是他们删除重复项;我想保留这些欺骗行为并将其收集在列表中。
答案 0 :(得分:1)
执行此操作的最简单方法是使用nub
和\\
:
import Data.List (nub, (\\))
getDups :: Eq a => [a] -> [a]
getDups xs = xs \\ nub xs
如果您可以使用Ord
约束,那么一切都会变得更好:
import Data.Set (member, empty, insert)
getDups :: Ord a => [a] -> [a]
getDups xs = foldr go (const []) xs empty
where
go x cont seen
| member x seen = x : r seen
| otherwise = r (insert x seen)
答案 1 :(得分:1)
我写了这些似乎运作良好的功能。
第一个返回列表中的duplicates元素列表,其中包含基本的equlity测试(==
)
duplicate :: Eq a => [a] -> [a]
duplicate [] = []
duplicate (x:xs)
| null pres = duplicate abs
| otherwise = x:pres++duplicate abs
where (pres,abs) = partition (x ==) xs
第二个通过提供相等测试功能(如nubBy
)
duplicateBy :: (a -> a -> Bool) -> [a] -> [a]
duplicateBy eq [] = []
duplicateBy eq (x:xs)
| null pres = duplicateBy eq abs
| otherwise = x:pres++duplicateBy eq abs
where (pres,abs) = partition (eq x) xs
答案 2 :(得分:0)
是否有一个Haskell函数接受一个列表并返回该列表中的重复/冗余元素列表?
你可以很容易地自己编写这样的功能。使用一个带有两个列表参数的辅助函数,第一个是查找其欺骗的列表;沿着那个列表走,并在第二个参数中积累欺骗;最后,当第一个参数是空列表时返回后者。
dupes l = dupes' l []
where
dupes' [] ls = ls
dupes' (x:xs) ls
| not (x `elem` ls) && x `elem` xs = dupes' xs (x:ls)
| otherwise = dupes' xs ls
测试:
λ> dupes [1,2,3,3,2,2,3,4]
[3,2]
请注意渐近时间复杂度与nub
的渐近时间复杂度一样糟糕:O(n ^ 2)。如果你想要更好的渐近线,你需要一个Ord
类约束。
答案 3 :(得分:0)
如果您对Ord
约束感到满意,可以使用group
中的Data.List
:
getDups :: Ord a => [a] -> [a]
getDups = concatMap (drop 1) . group . sort