重複の削除

30分プログラム、その131。重複する要素の削除

重複した要素が、すべて削除されるところがnubと違う。

> nub [1,1]
*Main> nub [1,1]
[1]

*Main> uniq [1,1]
[]

使い方

普通につくったuniqと、ちょっと工夫したuniq2がある。
たぶん、uniqはO(N*N)で、uniq2は(N)。ちゃんと計算したわけじゃないけど。

*Main> :set +s
*Main> let xs = [1..1000] ++ [1..1000]

*Main> uniq (xs++xs)
[]
(0.53 secs, 16557356 bytes)

*Main> uniq2 (xs++xs)
[]
(0.21 secs, 3464192 bytes)

よし、ちゃんと効率がよくなってる。

ソースコード

import Data.List
uniq :: (Eq a) =>[a] -> [a]
uniq (x:xs) = if x `elem` xs then
                  delete x $ uniq xs
              else
                  x:uniq xs
uniq [] = []

delTopBy f x l@(y:ys) 
    | f x y    = delTopBy f x ys
    | otherwise = l
delTopBy _ _ [] = []

nodupBy :: (Eq a) => (a->a->Bool)->[a] -> [a]
nodupBy f (x:l@(y:xs)) = if f x y then
                             nodupBy f $ delTopBy f x xs
                         else
                             x:(nodupBy f l)
nodupBy _ x = x

uniq2 xs = map fst $ 
           sortBy (compose compare snd) $
           nodupBy (compose (==) fst) $
           sortBy (compose compare fst) $
           zip xs [0..]
    where
      compose f g a b = f (g a) (g b) -- これ標準でありそう