查找列表中的第一个重复元素

时间:2011-03-25 22:05:08

标签: haskell functional-programming

我对Haskell很新。我试图在Haskell中编写代码,从列表中找到第一个重复元素,如果它没有重复元素,则给出消息没有重复。我知道我可以通过nub函数来实现它,但我试图在没有它的情况下完成它。

3 个答案:

答案 0 :(得分:6)

这是一种方法:

import qualified Data.Set as Set

dup :: Ord a => [a] -> Maybe a
dup xs = dup' xs Set.empty
  where dup' [] _ = Nothing
        dup' (x:xs) s = if Set.member x s 
                           then Just x
                           else dup' xs (Set.insert x s)

dupString :: (Ord a, Show a) => [a] -> [Char]
dupString x = case dup x of
                  Just x  -> "First duplicate: " ++ (show x)
                  Nothing -> "No duplicates"

main :: IO ()
main = do
       putStrLn $ dupString [1,2,3,4,5]
       putStrLn $ dupString [1,2,1,2,3]
       putStrLn $ dupString "HELLO WORLD"

以下是它的工作原理:

*Main> main
No duplicates
First duplicate: 1
First duplicate: 'L'

答案 1 :(得分:0)

这不是你的最终答案,因为当元素被多次复制而不是立即返回时,它会做不必要的工作,但它说明了如何系统地运行所有可能性(即“列表在列表的下方有重复吗?“)

dupwonub :: Eq a => [a] -> [a]
dupwonub [] = []
dupwonub (x:xs) = case [ y | y <- xs, y == x ] of
                    (y:ys) -> [y]
                    []     -> dupwonub xs

答案 2 :(得分:0)

如果你还在研究Haskell,我认为你可能想要一个更快但更复杂的解决方案。这在O(n)(我认为)中运行,但对列表的类型有一个稍微严格的限制,即必须是Ix类型。

accumArray是一个非常有用的功能,如果你还没有,真的建议你去研究它。

import Data.Array

data Occurances = None | First | Duplicated
                deriving Eq

update :: Occurances -> a -> Occurances
update None _ = First
update First _ = Duplicated
update Duplicated _ = Duplicated

firstDup :: (Ix a) => [a] -> a
firstDup xs = fst . first ((== Duplicated).snd) $ (map g xs)
  where dupChecker = accumArray update None (minimum xs,maximum xs) (zip xs (repeat ()))
        g x = (x, dupChecker ! x)

first :: (a -> Bool) -> [a] -> a
first _ [] = error "No duplicates master"
first f (x:xs) = if f x
                 then x
                 else first f xs

注意,一个大小为(minimum xs,maximum xs)的数组可能真的会破坏你的空间需求。