How to split a list into equal sized lists in Groovy?

29,213

Solution 1

I agree with Chris that there isn't anything built into groovy to handle this (at least for more than 2 partitions), but I interpreted your question to be asking something different than he did. Here's an implementation that does what I think you're asking for:

def partition(array, size) {
    def partitions = []
    int partitionCount = array.size() / size

    partitionCount.times { partitionNumber ->
        def start = partitionNumber * size 
        def end = start + size - 1
        partitions << array[start..end]    
    }

    if (array.size() % size) partitions << array[partitionCount * size..-1]
    return partitions    
}


def origList = [1, 2, 3, 4, 5, 6]
assert [[1], [2], [3], [4], [5], [6]] == partition(origList, 1)
assert [[1, 2], [3, 4], [5, 6]] == partition(origList, 2)
assert [[1, 2, 3], [4, 5, 6]] == partition(origList, 3)
assert [[1, 2, 3, 4], [5, 6]] == partition(origList, 4)
assert [[1, 2, 3, 4, 5], [6]] == partition(origList, 5)
assert [[1, 2, 3, 4, 5, 6]] == partition(origList, 6)

Solution 2

EDIT As of groovy 1.8.6 you can use the collate method on lists

def origList = [1, 2, 3, 4, 5, 6, 7, 8, 9]
assert [[1, 2, 3, 4], [5, 6, 7, 8], [9]] == origList.collate(4)

Another method using inject and metaClasses

List.metaClass.partition = { size ->
  def rslt = delegate.inject( [ [] ] ) { ret, elem ->
    ( ret.last() << elem ).size() >= size ? ret << [] : ret
  }
  if( rslt.last()?.size() == 0 ) rslt.pop()
  rslt
}

def origList = [1, 2, 3, 4, 5, 6]

assert [ [1], [2], [3], [4], [5], [6] ] == origList.partition(1)
assert [ [1, 2], [3, 4], [5, 6] ]       == origList.partition(2)
assert [ [1, 2, 3], [4, 5, 6] ]         == origList.partition(3)
assert [ [1, 2, 3, 4], [5, 6] ]         == origList.partition(4)
assert [ [1, 2, 3, 4, 5], [6] ]         == origList.partition(5)
assert [ [1, 2, 3, 4, 5, 6] ]           == origList.partition(6)
assert [ ]                              == [ ].partition(2)

Edit: fixed an issue with the empty list

Solution 3

Check out groovy 1.8.6. There is a new collate method on List.

def list = [1, 2, 3, 4]
assert list.collate(4) == [[1, 2, 3, 4]] // gets you everything   
assert list.collate(2) == [[1, 2], [3, 4]] //splits evenly
assert list.collate(3) == [[1, 2, 3], [4]] // won't split evenly, remainder in last list.

Take a look at the Groovy List documentation for more info because there are a couple of other params that give you some other options, including dropping the remainder.

Solution 4

I was looking for the same problem and I found the collate() method for lists to be very useful.

array.collate(2)

Here is the link to the documentation.

Solution 5

There is nothing builtin to do that but it is not hard to write:

def array = [1,2,3,4,5,6]
int mid = (int) (array.size() / 2)
def left = array[0..mid-1]
def right = array[mid..array.size()-1]

println left
println right
Share:
29,213

Related videos on Youtube

MarkD
Author by

MarkD

Updated on July 09, 2022

Comments

  • MarkD
    MarkD almost 2 years

    If I have this:

    def array = [1,2,3,4,5,6]
    

    Is there some built-in which allows me to do this ( or something similar ):

    array.split(2)
    

    and get:

    [[1,2],[3,4],[5,6]]
    

    ?

    • tim_yates
      tim_yates about 12 years
      As of groovy 1.8.6 you can use the collate method on lists
  • MarkD
    MarkD almost 14 years
    Yeah. This is what I was looking for. I ended up writing my own last night. Thanks!
  • sbglasius
    sbglasius over 13 years
    right side can be defined as right = array[mid..-1] (The Groovy way!)
  • raffian
    raffian about 12 years
    @Ted Possible concurrency issue with this function in some scenarios, but easily addressable, stackoverflow.com/questions/9536552/…