Haskell - remove adjacent duplicates from a list

I am trying to learn haskell by solving some problems online and training exercises.

Now I'm trying to create a function that removes neighboring duplicates from a list.

Input example

"acvvca"

"1456776541"

"abbac"

"aabaabckllm"


Expected Result

"

""

" with "

"CKM"

My first, though, was to make a function that simply deletes the first instance of neighboring duplicates and restores the list.

module Test where

removeAdjDups :: (Eq a) => [a] -> [a]
removeAdjDups []           =  []
removeAdjDups [x]          =  [x]
removeAdjDups (x : y : ys)
  | x == y = removeAdjDups ys
  | otherwise = x : removeAdjDups (y : ys)

*Test> removeAdjDups "1233213443"
"122133"

This function works for found pairs.

So now I need to apply the same function to the result of the function.

Something I think about can help, but I don’t know how I would implement it.

Something along the line

removeAdjDups' xs = foldl (\acc x -> removeAdjDups x acc) xs

Is this approach also the best way to implement the solution, or is there a better way I should think about?

+1
4

: , , ( , ):

main = mapM_ (print . squeeze) ["acvvca", "1456776541", "abbac", "aabaabckllm"]

squeeze :: Eq a => [a] -> [a]
squeeze (x:xs) = let ys = squeeze xs in case ys of
                                            (y:ys') | x == y -> ys'
                                            _ -> x:ys
squeeze _ = []

""
""
"c"
"ckm"
+3

, foldl . ( , foldl foldr foldl'... , foldMap, , , foldl.)

, : removeAdjDups, . -

iterate :: (a -> a) -> a -> [a]

Prelude> iterate removeAdjDups "1233213443"
["1233213443","122133","11","","","","","","","","","","","","","","","","","","","","","","","","","","",""...

. , ; . , fixpoint; , removeAdjDups: , .

bipll , .

+2

. , , , , , . -, . , . .

(\l -> [ x  | (x,y) <- zip l $ (tail l) ++ " ", x /= y]) "abcddeeffa"

"abcdefa"

0

, foldl. , , - , foldr.

main = mapM_ (print . squeeze) ["acvvca", "1456776541", "abbac", "aabaabckllm"]

-- I like the name in @bipll answer
squeeze = foldr (\ x xs -> if xs /= "" && x == head(xs) then tail(xs) else x:xs) ""

Let's analyze this. Idea taken from @bipll answer: go from right to left. If fis a lambda function, then by definition foldr:

squeeze "abbac" = f('a' f('b' f('b' f('a' f('c' "")))

By definition f, f('c' "") = 'c':"" = "c"since xs == "". Next char on the right: f('a' "c") = 'a':"c" = "ac"p 'a' != head("c") = 'c'. f('b' "ac") = "bac"for the same reason. But f('b' "bac") = tail("bac") = "ac"because 'b' == head("bac"). Etc...

Bonus: replacing foldrwith scanr, you can see the whole process:

Prelude> squeeze' = scanr (\ x xs -> if xs /= "" && x == head(xs) then tail(xs) else x:xs) ""
Prelude> zip "abbac" (squeeze' "abbac")
[('a',"c"),('b',"ac"),('b',"bac"),('a',"ac"),('c',"c")]
0
source

Source: https://habr.com/ru/post/1695200/


All Articles