2010-05-27 123 views
16

如果我有这样的:如何在Groovy中将列表拆分为相同大小的列表?

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

有一些内置的,让我做这个(或类似的东西):

array.split(2) 

,并得到:

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

+5

由于groovy 1.8.6你可以使用[collat​​e method](http://jira.codehaus.org/browse/GROOVY-5283)在列表 – 2012-02-09 21:51:45

回答

15

我与克里斯同意,没有内置常规来处理这事(至少超过2个分区),但我把你的问题解释为问一些与他不同的问题。下面是一个实现,它做什么,我想你问:

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) 
+0

是的。这是我正在寻找的。我昨晚写了自己的作品。谢谢! – Geo 2010-05-28 08:23:28

+0

@Ted在某些情况下使用此函数可能发生并发问题,但容易寻址,http://stackoverflow.com/questions/9536552/groovy-collat​​ing-list-causes-concurrentmodification-exception – raffian 2012-03-02 21:09:52

2

没有什么内建要做到这一点,但它并不难写:

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

右侧可以定义为right = array [mid .. -1](Groovy方式!) – sbglasius 2010-11-03 07:52:59

2

这里有一个替代版本,使用Groovy的动态功能来划分方法添加到列表类,已经做了你所期望的:

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) 
47

编辑作为常规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) 

编辑:固定的问题与空列表

9

退房常规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 documentation更多的信息,因为有一对夫妇,让你一些其他的选择,包括丢弃其余为其他则params的。

1
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

这个问题是旧的,但我想分享我想出了什么来分裂列表在同等大小的列表。

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) 
} 
2

我知道这是超级老 - 但对于那些希望拆分列表分成相等的分区(与余数),和你错过在原来的岗位Tim的评论,最近的groovy方法是自Groovy 1.8.6以来可用的List对象的collat​​e()方法。

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) 
3

我在找同样的问题,我发现collate()方法列表非常有用。

array.collate(2) 

Here是链接到文档。