``````unique :: Ord a => [a] -> [a]
unique li = first \$ filter ((==1).length) ((group.sort) li)
where first [] = []
first (x:xs) = x

ghci> unique [3,5,6,8,3,9,3,5,6,9,3,5,6,9,1,5,6,8,9,5,6,8,9]
ghci> [1]
``````

## 6 个回复6

### ===============>>#1 票数：12 已采纳

``````import qualified Data.IntTrie as IntTrie
import Data.List (foldl')
import Control.Applicative
``````

``````counts :: (Enum a) => [a] -> (a -> Int)
counts xs = IntTrie.apply (foldl' insert (pure 0) xs) . fromEnum
where
insert t x = IntTrie.modify' (fromEnum x) (+1) t
``````

``````uniques :: (Eq a, Enum a) => [a] -> [a] -> [a]
uniques dom xs = filter (\x -> cts x == 1) dom
where
cts = counts xs
``````

`uniques`遍历域一次（懒惰，所以`head . uniques dom`只会遍历它需要找到第一个唯一元素 - 不在列表中，但在`dom` ），对于运行查找函数的每个元素我们都有建立的是O（log d） ，因此过滤器需要O（d log d） ，并且构建计数表需要O（m log d） 因此， `uniques`运行在O（（m + d）log d）中 ，当d被固定时，它是线性的。 至少需要Ω（m log d）才能从中获取任何信息，因为它必须遍历整个列表才能构建表（你必须一直到列表的末尾才能看到元素是否是反复，所以你不能比这更好）。

### ===============>>#2 票数：6

``````unique [] _ _ = Nothing
unique _ [] [] = Nothing
unique _ (r:_) [] = Just r
unique candidates results (x:xs)
| x `notElem` candidates = unique candidates results xs
| x `elem` results       = unique (delete x candidates) (delete x results) xs
| otherwise              = unique candidates (x:results) xs
``````

### ===============>>#3 票数：2

``````firstUnique (x:xs)
| elem x xs = firstUnique (filter (/= x) xs)
| otherwise = Just x
firstUnique [] = Nothing
``````

``````firstUnique = f [] [<small/known set of possible elements>] where
f [] [] _ = Nothing  -- early out
f uniques noshows (x:xs)
| elem x uniques = f (delete x uniques) noshows xs
| elem x noshows = f (x:uniques) (delete x noshows) xs
| otherwise      = f uniques noshows xs
f []    _ [] = Nothing
f (u:_) _ [] = Just u
``````

### ===============>>#4 票数：2

``````import Data.List (foldl', find)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)

count :: (Ord a) => Map a Int -> a -> Int
count m x = fromMaybe 0 \$ Map.lookup x m

add :: (Ord a) => Map a Int -> a -> Map a Int
add m x = Map.insertWith (+) x 1 m

uniq :: (Ord a) => [a] -> Maybe a
uniq xs = find (\x -> count cs x == 1) xs
where
cs = foldl' add Map.empty xs
``````

``````import Control.Monad
import Data.Hashable
import qualified Data.HashTable.ST.Basic as HT
import Data.Maybe (fromMaybe)

count :: (Eq a, Hashable a) => HT.HashTable s a Int -> a -> ST s Int
count ht x = liftM (fromMaybe 0) (HT.lookup ht x)

add :: (Eq a, Hashable a) => HT.HashTable s a Int -> a -> ST s ()
add ht x = count ht x >>= HT.insert ht x . (+ 1)

uniq :: (Eq a, Hashable a) => [a] -> Maybe a
uniq xs = runST \$ do
-- Count all elements into a hash table:
ht <- HT.newSized (length xs)
-- Find the first one with count 1
first (\x -> liftM (== 1) (count ht x)) xs

-- Monadic variant of find which exists once an element is found.
first :: (Monad m) => (a -> m Bool) -> [a] -> m (Maybe a)
first p = f
where
f []        = return Nothing
f (x:xs')   = do
b <- p x
if b then return (Just x)
else f xs'
``````

• 如果您知道列表中只有少量不同的元素，则可以使用`HT.new`而不是`HT.newSized (length xs)` 这将节省你一些内存和一次通过`xs`但在许多不同的元素的情况下，哈希表将不得不重新调整几次。

### ===============>>#5 票数：1

``````unique :: Eq a => [a] -> [a]
unique =  select . collect []
where
collect acc []              = acc
collect acc (x : xs)        = collect (insert x acc) xs

insert x []                 = [[x]]
insert x (ys@(y : _) : yss)
| x == y                  = (x : ys) : yss
| otherwise               = ys : insert x yss

select []                   = []
select ([x] : _)            = [x]
select ((_ : _) : xss)      = select xss
``````

### ===============>>#6 票数：0

``````unique = fst . foldl' (\(a, b) c -> if (c `elem` b)
then (a, b)
else if (c `elem` a)
then (delete c a, c:b)
else (c:a, b)) ([],[])
``````

``````import Data.List (foldl', delete, elem)

unique :: Eq a => [a] -> [a]
unique = fst . foldl' algorithm ([], [])
where
algorithm (result0, memory0) current =
if (current `elem` memory0)
then (result0, memory0)
else if (current`elem` result0)
then (delete current result0, memory)
else (result, memory0)
where
result = current : result0
memory = current : memory0
``````

``````unique' :: Eq a => [a] -> [a]
unique' = fst . foldl' algorithm ([], [])
where
algorithm (result, memory) current =
if (current `elem` memory)
then (result, memory)
else helper current result memory []
where
helper current [] [] acc = ([current], [])
helper current [] memory acc = (acc, memory)
helper current (r:rs) memory acc
| current == r    = (acc ++ rs, current:memory)
| otherwise = helper current rs memory (r:acc)
``````

``````helper current [] _ = ([current],[])
helper current memory result =
foldl' (\(r, m) x -> if x==current
then (r, current:m)
else (current:r, m)) ([], memory) \$ result
``````