Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eliminate consecutive duplicates from a string

Tags:

haskell

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?


2 Answers

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
like image 114
Willem Van Onsem Avatar answered Feb 18 '26 04:02

Willem Van Onsem


I want to eliminate consecutive duplicates from a string like f "aaabbbcccdeefgggg" = "abcdefg"

You can group the letters which are equal (via Data.List.group), and then take the first of each group (via map head, which applies head to each element of the list and gives you back the list of the results):

import Data.List (group) -- so we write group instead of Data.List.group
map head $ group "aaabbbcccdeefgggg"

This can be seen as the application of map head after the application of group to the input String. Therefore, your f can be defined like the composition of those two functions:

f :: String -> String
f = map head . group

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 as f (a b c);
  • . is the composition operator, and it is such that (f . g) x == f (g x).
    • Unrelated to this question, but important to bear in mind in general, . operates on unary functions, which means that if g takes more than one argument, the composition will pipe a partially applied g to f as soon as you give f . g one argument. In other words, if g is, say, binary, then f (g x y) is not equal to (f . g) x y, which will generally not even compile, but to ((f .) . g) x y. Some more example about this, but in JavaScript, is in this answer of mine, which should be fairly readable for a Haskell programmer.
like image 45
Enlico Avatar answered Feb 18 '26 05:02

Enlico



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!