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'. なぜそこに行くのですか?私はコードを大幅に変更してきましたが、なぜこれが行われるのかわかりません。

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 に答える