Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split a list at the first occurrence of an element

Tags:

haskell

I was wondering if there is a function that lets me split a list at the first occurrence of an element, excluding that element. Basically, suppose:

listT= [1,3,2,5,6,3,2,6]

then I want to define (or not, if it already exists), a function splitAtFirst so that

splitAtFirst 2 listT = [[1,3],[5,6,3,2,6]]

my attempt so far looks like this:

splitAtfirst::(Eq a)=> a->[a]->[[a]]
splitAtfirst _ []=[]
splitAtfirst a (x:xs) 
   |a==x        = [xs]
   |otherwise   = [x]: splitAtfirst a (xs) 

However, I get

>splitAtfirst 2 [1,3,2,5,6,3,2,6]
>[[1],[3],[5,6,3,2,6]]

I know why the problem happens, but so far I haven't been able to find a good solution

I appreciate any help!

Edit: this is an auxiliary function that only will be called after checking that elem is in the list, so dealing with the case when it does not exist it's not really necessary. I appreciate your help

like image 668
David Leonardo Ardila Herrera Avatar asked Dec 05 '22 16:12

David Leonardo Ardila Herrera


1 Answers

Since dfeuer has already pointed the way towards fixing your implementation, I will just chime in with the ready-made solution:

splitAtFirst :: Eq a => a -> [a] -> ([a], [a])
splitAtFirst x = fmap (drop 1) . break (x ==)

This splitAtFirst implements the second option from the three suggestions in dfeuer's answer. A few notes on each of the components:

  • (x ==) is a function which tests for equality with x, returning a Bool.

  • break uses a boolean test (here, (x ==)) to break a list in two, the second list beginning with the first element that passes the test. The two lists are returned as a pair (see dfeuer's answer for the reason why it is so).

  • drop 1 drops the first element of a list if it is not empty (and leaves it alone if it is empty).

  • fmap would take quite a bit longer to explain properly, so I will just say that fmap f applied on a pair (such as the result of break) applies the function f to the second element of the pair. In our case, fmap (drop 1) will remove the first element of the second list -- that is, the separator. (To find out more about fmap, search for the keyword "functor", or just try using it on a list or a Maybe-value and see what happens.)

like image 153
duplode Avatar answered Dec 09 '22 13:12

duplode