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
答案 0 :(得分:91)
答案 1 :(得分:49)
来自nub
的{{1}}函数(不,它实际上不在Prelude中)肯定会像您想要的那样,但它与您的Data.List
函数不完全相同。它们都保留了元素的原始顺序,但unique
保留了最后一个
每个元素的出现,而unique
保留第一次出现。
你可以这样做,使nub
行为与nub
完全相同,如果这很重要(虽然我感觉不是):
unique
此外,unique = reverse . nub . reverse
仅适用于小型列表。
它的复杂性是二次的,所以如果你的列表可以包含数百个元素,它就会变慢。
如果将类型限制为具有Ord实例的类型,则可以使其更好地扩展。
nub
上的此变体仍然保留了列表元素的顺序,但其复杂性为nub
:
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 _ _ = []
添加到nubOrd
已经proposed。
答案 2 :(得分:9)
import Data.Set (toList, fromList)
uniquify lst = toList $ fromList lst
答案 3 :(得分:4)
我认为unique应返回仅在原始列表中出现一次的元素列表;也就是说,不止一次出现的原始列表中的任何元素都不应包含在结果中。
我可以建议另一种定义,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 )
以下是一些突出unique_alt和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]
答案 4 :(得分:1)
我认为这会做到的。
unique [] = []
unique (x:xs) = x:unique (filter ((/=) x) xs)
答案 5 :(得分:0)
删除重复项的另一种方法:
unique :: [Int] -> [Int]
unique xs = [x | (x,y) <- zip xs [0..], x `notElem` (take y xs)]
答案 6 :(得分:0)
Haskell中创建唯一列表的算法:
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)
<强>输出:强>
Foo {id_ = 9, name_ = "Name"}
Foo {id_ = 9, name_ = "Gaby"}
Foo {id_ = 5, name_ = "Karl"}
Foo {id_ = 8, name_ = "Tim"}