2012-04-23 75 views
0
count :: Eq a => a -> [a] -> Int 
count _[]     = 0 
count z (x:xs) | z == x = 1 + (count z xs) 
       | otherwise = count z xs 

rmdups :: Eq a => [a] -> [a] 
rmdups [] = [] 
rmdups (x:xs) | count x xs > 0 = rmdups xs 
       | otherwise  = x: rmdups xs 

上述编译代码,但是当我输入'ababca' rmdups的输出为'bca',我希望它是'abc'。为什么一个去那里?我一直在改变这些代码,不知道为什么它会这样做。这为什么不给出正确的输出?

回答

10

因为您从前面删除重复项。您可以修改rmdups移动之前过滤掉xs,所以重复从尾淘汰:

rmdups :: Eq a => [a] -> [a] 
rmdups [] = [] 
rmdups (x:xs) 
    | count x xs > 0 = x : (rmdups $ filter (/= x) xs) 
    | otherwise  = x : rmdups xs 

事实上,你甚至可以做到这一点没有precounting:

rmdups :: Eq a => [a] -> [a] 
rmdups []  = [] 
rmdups (x : xs) = x : filtered 
       where filtered = rmdups $ filter (/= x) xs 

,当然还有在实际代码中,您应该宁愿使用已有的函数,在这种情况下为Data.List.nub

1

您的rmdups函数删除除了之外的所有字符,最后一个发生每个字符。

如果你想删除所有除第一发生的每个字符,你可以尝试

reverse . rmdups . reverse 

(即之前使用rmdups后反转),或者你可以重写rmdups保持跟踪所有先前发生的字符。