2010-05-27 8 views

Trả lời

15

Tôi đồng ý với Chris rằng không có bất cứ điều gì được xây dựng vào groovy để xử lý này (ít nhất là trong hơn 2 phân vùng), nhưng tôi đã giải thích câu hỏi của bạn để hỏi điều gì đó khác với anh ấy. Dưới đây là một thực hiện mà những gì tôi nghĩ rằng bạn đang yêu cầu cho:

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

Vâng. Đây là những gì tôi đang tìm kiếm. Tôi đã kết thúc bằng văn bản đêm cuối cùng của riêng tôi. Cảm ơn! – Geo

+0

@Ted Có thể xảy ra sự cố đồng thời với hàm này trong một số trường hợp, nhưng dễ dàng giải quyết được, http://stackoverflow.com/questions/9536552/groovy-collating-list-causes-concurrentmodification-exception – raffian

2

Không có gì được xây dựng trong để làm điều đó là nhưng nó không phải là khó để viết:

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

bên phải có thể được định nghĩa là right = array [mid .. -1] (Cách Groovy!) – sbglasius

2

Dưới đây là một phiên bản thay thế, sử dụng tính năng động Groovy để thêm một phương pháp phân chia đến lớp List, mà những gì bạn mong đợi:

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

EDIT Tính đến 1.8.6 groovy bạn có thể sử dụng phương pháp collate vào danh sách

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

Phương pháp khác sử dụng bơm và 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: cố định một vấn đề với danh sách trống

9

Check-out groovy 1.8.6. Có một phương thức đối chiếu mới trong Danh sách.

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. 

Hãy nhìn vào các Groovy List documentation để biết thêm vì có một vài params khác mà cung cấp cho bạn một số tùy chọn khác, bao gồm giảm thời gian còn lại.

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

Câu hỏi này cũ nhưng tôi muốn chia sẻ những gì tôi nghĩ ra để chia nhỏ danh sách trong danh sách có kích thước bằng nhau.

list.collate thật tuyệt, nhưng không hiệu quả đối với tôi, vì tôi cần danh sách được chia đều.

đâu là những gì tôi làm:

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

Tôi biết đây là siêu cũ - nhưng đối với những ai muốn chia danh sách thành các phân vùng tương đương (với dư), và bạn bỏ lỡ comment của Tim trên bài đăng gốc, cách thức hấp dẫn gần đây nhất là phương thức collate() cho các đối tượng Danh sách đã có sẵn từ 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) 
3

Tôi đang tìm cùng một vấn đề và tôi đã tìm thấy phương pháp collate() cho danh sách rất hữu ích.

array.collate(2) 

Here là liên kết đến tài liệu.