Как разбить список на списки одинакового размера в Groovy? - PullRequest
19 голосов
/ 27 мая 2010

Если у меня есть это:

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

Есть ли какая-то встроенная функция, которая позволяет мне сделать это (или что-то подобное):

array.split(2)

и получите:

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

Ответы [ 9 ]

57 голосов
/ 28 мая 2010

РЕДАКТИРОВАТЬ Начиная с Groovy 1.8.6 вы можете использовать метод сортировки в списках

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

Другой метод с использованием inject и 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)

Редактировать: исправлена ​​проблема с пустым списком

15 голосов
/ 28 мая 2010

Я согласен с Крисом, что нет ничего встроенного в Groovy, чтобы справиться с этим (по крайней мере, для более чем двух разделов), но я истолковал ваш вопрос так, чтобы он задавал что-то другое, чем он. Вот реализация, которая делает то, о чем я думаю, вы просите:

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)
11 голосов
/ 01 июня 2012

Ознакомьтесь с заводной 1.8.6. В 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.

Ознакомьтесь с документацией Groovy List для получения дополнительной информации, потому что есть пара других параметров, которые дают вам некоторые другие опции, включая удаление оставшейся части.

6 голосов
/ 06 февраля 2015

Я искал ту же проблему и обнаружил, что метод collate() для списков очень полезен.

array.collate(2)

Здесь - ссылка на документацию.

2 голосов
/ 20 июня 2013

Я знаю, что это очень старое - но для тех, кто хочет разбить список на равные разделы (с остатками), и вы пропустите комментарий Тима к исходному сообщению, самый свежий способ - метод collate () для объектов List это было доступно начиная с Groovy 1.8.6.

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

assert [[1], [2], [3], [4], [5], [6], [7]] == array.collate(1, 1, true)
assert [[1, 2], [3, 4], [5, 6], [7]] == array.collate(2, 2, true)
assert [[1, 2, 3], [4, 5, 6], [7]] == array.collate(3, 3, true)
assert [[1, 2, 3, 4], [5, 6, 7]] == array.collate(4, 4, true)
assert [[1, 2, 3, 4, 5], [6, 7]] == array.collate(5, 5, true)
assert [[1, 2, 3, 4, 5, 6], [7]] == array.collate(6, 6, true)
assert [[1, 2, 3, 4, 5, 6, 7]] == array.collate(7, 7, true)
2 голосов
/ 28 мая 2010

Вот альтернативная версия, которая использует динамические функции Groovy для добавления метода split в класс List, который делает то, что вы ожидаете:

List.metaClass.split << { size ->
  def result = []
  def max = delegate.size() - 1
  def regions = (0..max).step(size)

  regions.each { start ->
     end =  Math.min(start + size - 1, max)
     result << delegate[start..end]
  }

  return result
}

def original = [1, 2, 3, 4, 5, 6]
assert [[1, 2], [3, 4], [5, 6]] == original.split(2)
2 голосов
/ 28 мая 2010

Нет ничего встроенного, чтобы сделать это, но это не сложно написать:

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
1 голос
/ 26 сентября 2012
List.metaClass.split << { step ->
    def result = [], max = delegate.size(), min = 0 

    while(min+step < max){       
        result.add delegate.subList(min,min+=step)
    }
    result.add delegate.subList(min, max)

    result
}
0 голосов
/ 11 января 2013

Этот вопрос старый, но я все равно хочу поделиться тем, что я придумала, чтобы разделить список на списки одинакового размера.

list.collate отлично, но у меня не получилось, так как мне нужно было равномерно разделить списки.

Где я делаю:

class PartitionCategory {

    static evenlyPartitionWithCount(Collection self, int count) {
        def indexes = 0..<self.size()
        def sizes = indexes.countBy({ i -> i % count }).values()
        def ranges = sizes.inject([]) { a, v -> a << (a ? (a.last().last() + 1)..(a.last().last() + v) : 0..<v) }
        ranges.collect { r -> self[r] }
    }

    static evenlyPartitionWithSize(Collection self, int size) {
        self.evenlyPartitionWithCount((int) Math.ceil(self.size() / size))
    }

}

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

use (PartitionCategory) {
assert [[1], [2], [3], [4], [5], [6], [7]] == array.evenlyPartitionWithSize(1)
assert [[1, 2], [3, 4], [5, 6], [7]] == array.evenlyPartitionWithSize(2)
assert [[1, 2, 3], [4, 5], [6, 7]] == array.evenlyPartitionWithSize(3)
assert [[1, 2, 3, 4], [5, 6, 7]] == array.evenlyPartitionWithSize(4)
assert [[1, 2, 3, 4], [5, 6, 7]] == array.evenlyPartitionWithSize(5)
assert [[1, 2, 3, 4], [5, 6, 7]] == array.evenlyPartitionWithSize(6)
assert [[1, 2, 3, 4, 5, 6, 7]] == array.evenlyPartitionWithSize(7)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...