unique elements in a haskell list

前端 未结 7 1879
有刺的猬
有刺的猬 2020-12-13 17:03

okay, this is probably going to be in the prelude, but: is there a standard library function for finding the unique elements in a list? my (re)implementation, for clarificat

相关标签:
7条回答
  • 2020-12-13 17:35
    import Data.Set (toList, fromList)
    uniquify lst = toList $ fromList lst
    
    0 讨论(0)
  • 2020-12-13 17:39

    I think that unique should return a list of elements that only appear once in the original list; that is, any elements of the orginal list that appear more than once should not be included in the result.

    May I suggest an alternative definition, unique_alt:

        unique_alt :: [Int] -> [Int]
        unique_alt [] = []
        unique_alt (x:xs)
            | elem x ( unique_alt xs ) = [ y | y <- ( unique_alt xs ), y /= x ]
            | otherwise                = x : ( unique_alt xs )
    

    Here are some examples that highlight the differences between unique_alt and unqiue:

        unique     [1,2,1]          = [2,1]
        unique_alt [1,2,1]          = [2]
    
        unique     [1,2,1,2]        = [1,2]
        unique_alt [1,2,1,2]        = []
    
        unique     [4,2,1,3,2,3]    = [4,1,2,3]
        unique_alt [4,2,1,3,2,3]    = [4,1]
    
    0 讨论(0)
  • 2020-12-13 17:53

    The nub function from Data.List (no, it's actually not in the Prelude) definitely does something like what you want, but it is not quite the same as your unique function. They both preserve the original order of the elements, but unique retains the last occurrence of each element, while nub retains the first occurrence.

    You can do this to make nub act exactly like unique, if that's important (though I have a feeling it's not):

    unique = reverse . nub . reverse
    

    Also, nub is only good for small lists. Its complexity is quadratic, so it starts to get slow if your list can contain hundreds of elements.

    If you limit your types to types having an Ord instance, you can make it scale better. This variation on nub still preserves the order of the list elements, but its complexity is O(n * log n):

    import qualified Data.Set as Set
    
    nubOrd :: Ord a => [a] -> [a] 
    nubOrd xs = go Set.empty xs where
      go s (x:xs)
       | x `Set.member` s = go s xs
       | otherwise        = x : go (Set.insert x s) xs
      go _ _              = []
    

    In fact, it has been proposed to add nubOrd to Data.Set.

    0 讨论(0)
  • 2020-12-13 17:54

    I think this would do it.

    unique [] = []
    unique (x:xs) = x:unique (filter ((/=) x) xs)
    
    0 讨论(0)
  • 2020-12-13 17:57

    Another way to remove duplicates:

    unique :: [Int] -> [Int]
    unique xs = [x | (x,y) <- zip xs [0..], x `notElem` (take y xs)]
    
    0 讨论(0)
  • 2020-12-13 17:57

    Algorithm in Haskell to create a unique list:

    data Foo = Foo { id_ :: Int
                   , name_ :: String
                   } deriving (Show)
    
    alldata = [ Foo 1 "Name"
              , Foo 2 "Name"
              , Foo 3 "Karl"
              , Foo 4 "Karl"
              , Foo 5 "Karl"
              , Foo 7 "Tim"
              , Foo 8 "Tim"
              , Foo 9 "Gaby"
              , Foo 9 "Name"
              ]
    
    isolate :: [Foo] -> [Foo]
    isolate [] = []
    isolate (x:xs) = (fst f) : isolate (snd f)
      where
        f = foldl helper (x,[]) xs
        helper (a,b) y = if name_ x == name_ y
                         then if id_ x >= id_ y
                              then (x,b)
                              else (y,b)
                         else (a,y:b)
    
    main :: IO ()
    main = mapM_ (putStrLn . show) (isolate alldata)
    

    Output:

    Foo {id_ = 9, name_ = "Name"}
    Foo {id_ = 9, name_ = "Gaby"}
    Foo {id_ = 5, name_ = "Karl"}
    Foo {id_ = 8, name_ = "Tim"}
    
    0 讨论(0)
提交回复
热议问题