Finding the first duplicate element in a list

只谈情不闲聊 提交于 2020-01-16 13:23:58

问题


I am very new to Haskell. I am trying to write code in Haskell that finds the first duplicate element from the list, and if it does not have the duplicate elements gives the message no duplicates. I know i can do it through nub function but i am trying to do it without it.


回答1:


This is one way to do it:

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"

Here is how it works:

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



回答2:


This is not the your final answer, because it does unnecessary work when an element is duplicated multiple times instead of returning right away, but it illustrates how you might go about systematically running through all the possibilities (i.e. "does this element of the list have duplicates further down the list?")

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



回答3:


In case you are still looking into Haskell I thought you might like a faster, but more complicated, solution. This runs in O(n) (I think), but has a slightly harsher restriction on the type of your list, namely has to be of type Ix.

accumArray is an incredibly useful function, really recommend looking into it if you haven't already.

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

Watch out tho, an array of size (minimum xs,maximum xs) could really blow up your space requirements.



来源:https://stackoverflow.com/questions/5438624/finding-the-first-duplicate-element-in-a-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!