I want to eliminate consecutive duplicates from a string like f "aaabbbcccdeefgggg" = "abcdefg"
This is my code
f :: String -> String
f "" = ""
f "_" = "_"
f (x : xs : xss)
| x == xs = f (xs : xss)
| otherwise = x : f (xs : xss)
I got as error non-exhaustive patterns, I think it's from second line, the program doesn't know how to deal when it's only 1 char left. How should I fix it?
CodePudding user response:
The "_"
pattern does not match a string with any character, it matches the string that contains an underscore.
You can use [_]
as pattern for the singleton string, so:
f :: String -> String
f "" = ""
f s@[_] = s
f (x : xs : xss)
| x == xs = f (xs : xss)
| otherwise = x : f (xs : xss)
here we use s@
to capture the string with one character as s
.
or we can simplify this with:
f :: String -> String
f (x : xs : xss)
| x == xs = f (xs : xss)
| otherwise = x : f (xs : xss)
f s = s
CodePudding user response:
This is an answer to the "title" of your question.
You can just group the letters which are equal, and then take the first of each group:
map head $ Data.List.group "aaabbbcccdeefgggg"
For completeness, as you seem to be new to Haskell, here are a few details:
Data.List.group "aaabbbcccdeefgggg"
returns["aaa","bbb","ccc","d","ee","f","gggg"]
;f $ a b c
is the same asf (a b c)
;- if you
import Data.List (group)
or more generallyimport Data.List
, then you can skip theData.List.
bit which fully qualifiesgroup
and use it unqualified:map head $ group "blaaa"
.
CodePudding user response:
Or you can make it even simpler if you don't handle things that can be left unhandled:
f :: String -> String
f (x:y:xs) | x == y = f (y:xs)
f (x:xs) = x:f xs
f _ = ""
CodePudding user response:
You also could use foldl
. the logic is: comparing the last element of accumulator with current element.
f :: Eq a => [a] -> [a]
f xs = foldl (\x y -> if last x == y then x else x [y] ) [head xs] xs
here we initiate our accumulator with [head x]
.