我对Haskell很新。我试图在Haskell中编写代码,从列表中找到第一个重复元素,如果它没有重复元素,则给出消息没有重复。我知道我可以通过nub
函数来实现它,但我试图在没有它的情况下完成它。
答案 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)
的数组可能真的会破坏你的空间需求。