Как разбить список на равные по размеру списки в Groovy?
Если у меня есть это:
def array = [1,2,3,4,5,6]
Есть ли встроенная встроенная функция, которая позволяет мне это делать (или что-то подобное):
array.split(2)
и получим:
[[1,2],[3,4],[5,6]]
?
Ответы
Ответ 1
Я согласен с Крисом в том, что для этого не существует ничего встроенного в 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)
Ответ 2
EDIT. По groovy 1.8.6 вы можете использовать метод collate в списках
def origList = [1, 2, 3, 4, 5, 6, 7, 8, 9]
assert [[1, 2, 3, 4], [5, 6, 7, 8], [9]] == origList.collate(4)
Другой метод, использующий инъекции и метаклассы
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)
Изменить: исправлена проблема с пустым списком
Ответ 3
Отъезд groovy 1.8.6. В списке есть новый метод сортировки.
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 Список документации для получения дополнительной информации, потому что есть еще пара параметров, которые дают вам некоторые другие параметры, включая отбрасывание остатка.
Ответ 4
Я искал ту же проблему, и я нашел метод collate()
для списков очень полезным.
array.collate(2)
Здесь - ссылка на документацию.
Ответ 5
Нет ничего встроенного в этом, но писать не сложно:
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
Ответ 6
Здесь альтернативная версия, которая использует динамические функции 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)
Ответ 7
Я знаю, что это супер старый, но для тех, кто хочет разбить список на равные разделы (с остатками), и вы пропустите комментарий Tim на исходном сообщении, самым последним способом groovy является метод collate() для Список объектов, которые были доступны с 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)
Ответ 8
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
}
Ответ 9
Этот вопрос старый, но я хочу разделить все, что я придумал, чтобы разбить список в равных размерах.
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)
}