Seliverstov
Seliverstov

Reputation: 47

Haskell. It is required to flatten the same elements in the list in the order they follow

How to remove identical duplicate items adjacent to the items in the list?

flattlst "aaaasssaaabbbssaaa"
--"asabsa"

I tried to do it through the "nub" function in the Data.List,

 import Data.List
 flattlst = nub
 --flattlst"aaaasssaaabbbssaaa"
"asb" -- !!! It is wrong!!
"asabsa" -- !!The answer should be like this.

but that is not what I need. The "Nub" removes all the same elements, but I only need those that go in a row.Help me solve this problem.

Upvotes: 0

Views: 95

Answers (2)

Robin Zigmond
Robin Zigmond

Reputation: 18249

Here's a naive approach that should work fine. It uses group from Data.List:

flattlst = map head . group

Most Haskell programmers, including me, generally warn against using head, as it will crash the program if used on an empty list. However, group is guaranteed to result in a list of non-empty lists*, so this should be OK.

*at least if the input is non-empty. I'm not sure what group does when used on an empty list - I suspect one way or another this will blowup, so add a special case for the empty list/string if that's important to avoid.

Upvotes: 3

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477210

nub will only yield an element, if it did not yield an equivalent element first. So nub indeed will emit "asb", since the 'a's, 's's and 'b's after that are already emitted.

What you can use is group :: (Eq a, Foldable f) => f a -> [NonEmpty a]. This will yield a non-empty list for each subsequence of equal elements. For example:

Prelude Data.List.NonEmpty> group "aaaasssaaabbbssaaa"
['a' :| "aaa",'s' :| "ss",'a' :| "aa",'b' :| "bb",'s' :| "s",'a' :| "aa"]

You still need to post-process this, such that for each NonEmpty element, you return the first element. I leave that as an exercise. Hint: you can use pattern matching for that.

Upvotes: 3

Related Questions