代码之家  ›  专栏  ›  技术社区  ›  Geo

如何在Groovy中将一个列表拆分为大小相等的列表?

  •  19
  • Geo  · 技术社区  · 16 年前

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

    是否有一些内置的允许我这样做(或类似的事情):

    array.split(2)
    

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

    ?

    9 回复  |  直到 13 年前
        1
  •  19
  •   Ted Naleid    16 年前

    我同意Chris的观点,groovy中没有任何东西可以处理这个问题(至少对于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)
    
        2
  •  75
  •   mkobit    8 年前

    从groovy1.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)
    

    另一种使用inject和元类的方法

    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
  •  14
  •   benkiefer    14 年前

    看看groovy1.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 List documentation 更多信息,因为有几个其他参数给你一些其他的选择,包括删除其余的。

        4
  •  9
  •   fhdrsdg    11 年前

    collate() 方法对列表非常有用。

    array.collate(2)
    

    Here

        5
  •  4
  •   Chris Dail    16 年前

    没有什么内在的东西可以做到这一点,但写起来并不难:

    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
  •  3
  •   Christoph Metzendorf    16 年前

    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
  •  2
  •   Mark    13 年前

    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
  •  1
  •   devside    13 年前
    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
  •  0
  •   Pierre-David Belanger    13 年前

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