Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Splitting list into sorted sublists

How can I divide a list [1,2,4,1,5,7,3,4,2,3] into a list of sublists that would be split at the values that break the sequence. For example a list [1,2,4,1,5,7,3,4,2,3] should yield a list of sublists like [[1,2,4],[1,5,7],[3,4],[2,3]].

Any ideas on this or suggestions how to resolve this problem?

Thanks.

like image 274
pacman. Avatar asked Nov 17 '10 23:11

pacman.


2 Answers

Like Travis above, my first thought is to zip the list with its own tail: However, it doesn't look like it quite works in this situation. Not only is there not really a split function that does exactly what you want, but there's also the issue that you will lose an element either off the beginning or the end. In lieu of a properly abstracted solution, take a look at this:

splitAscending :: Ord a => [a] -> [[a]]
splitAscending = foldr f [] where
    f x [] = [[x]]
    f x (y:ys) = if x < head y
    -- It's okay to call head here because the list y is
    -- coming from the summary value of the fold, which is [[a]].
    -- While the sum value may be empty itself (above case), it will
    -- never CONTAIN an empty list.  In general be VERY CAREFUL when
    -- calling head.
        then (x:y):ys -- prepend x to the first list in the summary value
        else [x]:y:ys -- prepend the new list [x] to the summary value

A quick and dirty solution, I hope it suits your needs

-- Also, this is my first post on Stack Overflow :)

like image 118
Jonathan Avatar answered Sep 20 '22 18:09

Jonathan


Here's a hint: whenever you need to look at consecutive elements while processing a list, it's a good idea to start by zipping the list against its tail:

Prelude> let f xs = zip xs $ tail xs
Prelude> f [1,2,4,1,5,7,3,4,2,3]
[(1,2),(2,4),(4,1),(1,5),(5,7),(7,3),(3,4),(4,2),(2,3)]

Now you can use something like splitWhen $ uncurry (>) (where splitWhen is from Data.List.Split) to divide the list appropriately.

like image 20
Travis Brown Avatar answered Sep 17 '22 18:09

Travis Brown