2012-04-23 135 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保持跟蹤所有先前發生的字符。