是否有一个函数采用列表并返回该列表中的重复元素列表?

时间:2015-03-05 21:22:17

标签: list haskell functional-programming

是否有一个Haskell函数接受一个列表并返回该列表中的重复/冗余元素列表?

我知道nubnubBy函数,但是他们删除重复项;我想保留这些欺骗行为并将其收集在列表中。

4 个答案:

答案 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