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'. 为什么a去那里?我一直在更改代码,但不知道为什么会这样。

4

2 回答 2

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

事实上,你甚至可以在不预先计算的情况下做到这一点:

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

当然,在实际代码中,您应该更喜欢已经可用的函数,在这种情况下是Data.List.nub.

于 2012-04-23T19:23:26.150 回答
1

您的rmdups函数会删除每个字符的最后一次出现以外的所有字符。

如果要删除每个字符的第一次出现以外的所有字符,可以尝试

reverse . rmdups . reverse

(即,在使用 rmdups 之前和之后反转),或者您可以重写rmdups以跟踪以前出现的所有字符。

于 2012-04-23T19:27:36.140 回答