Reputation: 63
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
The code above compiles but when I input 'ababca'
the output of rmdups is 'bca'
and I want it to be 'abc'
. Why does the a go there? I've been changing the code so much and have no clue why it does this.
Upvotes: 0
Views: 275
Reputation: 26097
Your rmdups
function removes all except the last occurrence of each character.
If you want to remove all except the first occurrence of each character, you could try
reverse . rmdups . reverse
(i.e., reverse before and after using rmdups), or you could rewrite rmdups
to keep track of all characters that have previously occurred.
Upvotes: 1
Reputation: 129764
Because you remove the duplicates from the front. You could modify rmdups
to filter out xs
before moving on, so the duplicates are weeded out from the tail:
rmdups :: Eq a => [a] -> [a]
rmdups [] = []
rmdups (x:xs)
| count x xs > 0 = x : (rmdups $ filter (/= x) xs)
| otherwise = x : rmdups xs
In fact, you could even do this without precounting:
rmdups :: Eq a => [a] -> [a]
rmdups [] = []
rmdups (x : xs) = x : filtered
where filtered = rmdups $ filter (/= x) xs
And of course, in real code, you should rather prefer already-available functions, in this case Data.List.nub
.
Upvotes: 10