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

发布于 2024-09-03 09:40:46 字数 213 浏览 6 评论 0原文

如果我有这个:

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

是否有一些内置功能可以让我执行此操作(或类似的操作):

array.split(2)

并获取:

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

If I have this:

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

Is there some built-in which allows me to do this ( or something similar ):

array.split(2)

and get:

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

?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

自找没趣 2024-09-10 09:40:47

我一直在寻找同样的问题,并且发现列表的 collat​​e() 方法非常有用。

array.collate(2)

此处是文档的链接。

I was looking for the same problem and I found the collate() method for lists to be very useful.

array.collate(2)

Here is the link to the documentation.

指尖上的星空 2024-09-10 09:40:47

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

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

There is nothing builtin to do that but it is not hard to write:

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
吻安 2024-09-10 09:40:47

这是一个替代版本,它使用 Groovy 的动态功能向 List 类添加 split 方法,它可以满足您的期望:

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)

Here's an alternative version, that uses Groovy's dynamic features to add a split method to the List class, that does what you expect:

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)
寒江雪… 2024-09-10 09:40:47

我知道这是非常旧的 - 但对于那些希望将列表分成相等的分区(带有余数)的人,并且您错过了 Tim 对原始帖子的评论,最新的常规方法是 List 对象的 collat​​e() 方法,该方法已被从 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)

I know this is super old - but for those looking to split a list into equal partitions (with remainders), and you miss Tim's comment on the original post, the most recent groovy way is the collate() method for List objects that has been available since 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)
老街孤人 2024-09-10 09:40:47
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
}
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
}
就此别过 2024-09-10 09:40:47

这个问题很老了,但无论如何我想分享我想出的将列表拆分为相等大小的列表的方法。

list.collat​​e 很棒,但对我来说不起作用,因为我需要均匀地分割列表。

我在哪里做:

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

This question is old, but I want to share anyway what I came up with to split a list in equal sized lists.

list.collate is great, but did not work for me, as I needed the lists to be split evenly.

Where is what I do:

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)
}
请止步禁区 2024-09-10 09:40:47

我的groovy很旧而且我没有柯林特。我实现了一个小型递归函数,其工作原理类似于Java中的Lists.partition,

private static partitionList(list, result, partitionSize) {
     if (list == []) {
         return result
     }

     if (list.size() <= partitionSize) {
         result.add(list[0..list.size() - 1])
         return result
     }

     result.add(list[0..partitionSize - 1])
     return partitionList(list[partitionSize..list.size() - 1], result, partitionSize)
}

private static partitionList(list, partitionSize) {
     return partitionList(list, [], partitionSize)
}

其工作原理如下

def arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
partitions = partitionList(arr1, 7)
assert partitions.size() == 2
assert partitions[0] == [1, 2, 3, 4, 5, 6, 7]
assert partitions[1] == [8, 9, 10, 11]

My groovy is old and I don't have colide. I've implemented a small recursive function that works like Lists.partition from Java

private static partitionList(list, result, partitionSize) {
     if (list == []) {
         return result
     }

     if (list.size() <= partitionSize) {
         result.add(list[0..list.size() - 1])
         return result
     }

     result.add(list[0..partitionSize - 1])
     return partitionList(list[partitionSize..list.size() - 1], result, partitionSize)
}

private static partitionList(list, partitionSize) {
     return partitionList(list, [], partitionSize)
}

which works like

def arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
partitions = partitionList(arr1, 7)
assert partitions.size() == 2
assert partitions[0] == [1, 2, 3, 4, 5, 6, 7]
assert partitions[1] == [8, 9, 10, 11]
眼角的笑意。 2024-09-10 09:40:46

编辑从 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)

另一种使用注入和元类的方法

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 As of groovy 1.8.6 you can use the collate method on lists

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

Another method using inject and 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: fixed an issue with the empty list

策马西风 2024-09-10 09:40:46

我同意 Chris 的观点,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)

I agree with Chris that there isn't anything built into groovy to handle this (at least for more than 2 partitions), but I interpreted your question to be asking something different than he did. Here's an implementation that does what I think you're asking for:

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)
混浊又暗下来 2024-09-10 09:40:46

查看 groovy 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 文档 了解更多信息,因为还有一些其他参数可以为您提供一些其他选项,包括删除其余部分。

Check out groovy 1.8.6. There is a new collate method on 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.

Take a look at the Groovy List documentation for more info because there are a couple of other params that give you some other options, including dropping the remainder.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文