Skip to content

groupWhen – a groupBy that compares consecutive values

groupBy has a minor problem: It always uses the first value of a group to decide whether a new value belongs to this group or the next. In several cases it would be more useful if it would take the last value of a group, thus always comparing consecutive values.

Example code:

groupWhen :: (a -> a -> Bool) -> [a] -> [[a]]
groupWhen _ []    = []
groupWhen _ [a]   = [[a]]
groupWhen f (a:l) = if f a (head c) then (a:c):r
                                    else [a]:c:r
  where (c:r) = groupWhen f l

Uses:

groupWhen (\a b -> b - a < 5) [1,2,4,10,14,16,18] -- Finding holes in a increasing series, e.g. log time stamps (my real use case)

or

groupWhen (<) [1,2,3,2,10,12,10,11] -- Group into strictly increasing sublists

Note that for transitive and symetrical comparision functions f (such as (==)), groupBy f == groupWhen f.

It should probably go to Data.List

Trac metadata
Trac field Value
Version 6.6.1
Type FeatureRequest
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component libraries (other)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system Unknown
Architecture Unknown
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information