tags:

views:

156

answers:

2

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 clarification, is:

has :: (Eq a) => [a] -> a -> Bool
has [] _ = False
has (x:xs) a
  | x == a    = True
  | otherwise = has xs a

unique :: (Eq a) => [a] -> [a]
unique [] = []
unique (x:xs)
  | has xs x  = unique xs
  | otherwise = x : unique xs
+16  A: 

I searched for (Eq a) => [a] -> [a] on Hoogle.

First result was nub (remove duplicate elements from a list).

Hoogle is awesome.

Artelius
Also, you can provide you own equality function like this : nubBy :: (a -> a -> Bool) -> [a] -> [a]
jdsc
And if Bart ever gets time we might see a nubOrd, which will be more reasonable performance wise.
TomMD
+11  A: 

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 e => [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.

Yitz