I have an array containing an unknown number of items that I would like to split into separate arrays so that each separate array contains no more than 4 items. What is the best way to do this in Groovy? Thanks!
Asked
Active
Viewed 5,911 times
3 Answers
9
We had this here: How to split a list into equal sized lists in Groovy?
I came up with this:
List.metaClass.partition = { size ->
def rslt = delegate.inject( [ [] ] ) { ret, elem ->
( ret.last() << elem ).size() >= size ? ret << [] : ret
}
!rslt.last() ? rslt[ 0..-2 ] : rslt
}
def list = [1, 2, 3, 4, 5, 6].partition( 4 )
Which should give you:
[ [ 1, 2, 3, 4 ], [ 5, 6 ] ]
Update!
With Groovy 1.8.6+ you can use list.collate( 4 )
to get the same result
-
2@RaffiM With Groovy 1.8.6+ [you can use `list.collate( 4 )`](http://blog.bloidonia.com/post/18073244930/whats-new-in-groovy-1-8-6-the-collate-method) to get the same result :-) – tim_yates Feb 29 '12 at 08:40
-
In a large application, where is the best place to define the `partition` method? Making it part of the `List.metaClass` is not practical since it only exists in the context of the groovy class where it's defined. – raffian Feb 29 '12 at 19:32
-
@RaffiM I would upgrade groovy and use `collate` ;-) failing that, if you add it at the startup cycle of your app. Or rewrite it as a category? – tim_yates Feb 29 '12 at 19:42
-
We're not using that Groovy version just yet...can the partition method be standalone, like a utility function? What parts would have to change? – raffian Feb 29 '12 at 20:06
-
1@RaffiM there's another functional version [over here](http://stackoverflow.com/a/2926548/6509) – tim_yates Feb 29 '12 at 20:40
6
Answer by tim_yates is cool, but it throws java.lang.ArrayIndexOutOfBoundsException
on empty lists (for example: [].partition(4)
). This can be fixed in this way:
List.metaClass.partition = {size ->
if (!delegate)
return []
def rslt = delegate.inject([[]]) {ret, elem ->
(ret.last() << elem).size() >= size ? (ret << []) : ret
}
!rslt.last() ? rslt[0..-2] : rslt
}
assert [].partition(4) == []
assert [1, 2, 3, 4, 5, 6].partition(4) == [[1, 2, 3, 4], [5, 6]]

Rorick
- 8,857
- 3
- 32
- 37
-
good catch! Could also turn last line into `!rslt[ 0 ] ? [] : !rslt.last() ? rslt[ 0..-2 ] : rslt` – tim_yates Jun 30 '10 at 21:15
-
@Rorick I tested the above with a list, and it works without changing a single thing in that function, does Groovy treat Lists and Arrays equally? – raffian Mar 01 '12 at 17:50
-
Mostly but there can be differences. For instance, list has no `length` property while arrays have. But in most cases arrays behave in the same way as lists. – Rorick Mar 05 '12 at 15:30
4
Since Groovy 1.8.6, you can use collate:
def letters = 'a'..'g'
assert letters.collate(3) == [['a', 'b', 'c'], ['d', 'e', 'f'], ['g']]
def letters = 'a'..'g'
assert letters.collate(3) == [['a', 'b', 'c'], ['d', 'e', 'f'], ['g']]
Credit to Mrhaki's Groovy goodness series: http://mrhaki.blogspot.com.au/2012/04/groovy-goodness-collate-list-into-sub.html

Armin
- 1,367
- 1
- 12
- 17