如何将任意长度的列表拆分为大小相等的块?


请参阅如果数据结果将直接用于循环,并且不需要存储,则如何以块形式遍历列表。

对于字符串输入的同一问题,请参见每n个字符拆分字符串?。相同的技术通常适用,但也有一些变化。


当前回答

简单而优雅

L = range(1, 1000)
print [L[x:x+10] for x in xrange(0, len(L), 10)]

或者如果您愿意:

def chunks(L, n): return [L[x: x+n] for x in xrange(0, len(L), n)]
chunks(L, 10)

其他回答

[AA[i:i+SS] for i in range(len(AA))[::SS]]

其中AA是数组,SS是块大小。例如:

>>> AA=range(10,21);SS=3
>>> [AA[i:i+SS] for i in range(len(AA))[::SS]]
[[10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20]]
# or [range(10, 13), range(13, 16), range(16, 19), range(19, 21)] in py3

要扩展py3中的范围,请执行以下操作

(py3) >>> [list(AA[i:i+SS]) for i in range(len(AA))[::SS]]
[[10, 11, 12], [13, 14, 15], [16, 17, 18], [19, 20]]

此时,我认为我们需要强制性的匿名递归函数。

Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
chunks = Y(lambda f: lambda n: [n[0][:n[1]]] + f((n[0][n[1]:], n[1])) if len(n[0]) > 0 else [])

这个问题让我想起Raku(以前的Perl6).comb(n)方法。它将字符串分成n个大小的块。(还有更多,但我会省略细节。)

在Python3中实现一个类似的函数作为lambda表达式非常简单:

comb = lambda s,n: (s[i:i+n] for i in range(0,len(s),n))

然后你可以这样称呼它:

some_list = list(range(0, 20))  # creates a list of 20 elements
generator = comb(some_list, 4)  # creates a generator that will generate lists of 4 elements
for sublist in generator:
    print(sublist)  # prints a sublist of four elements, as it's generated

当然,您不必将生成器分配给变量;你可以直接这样循环:

for sublist in comb(some_list, 4):
    print(sublist)  # prints a sublist of four elements, as it's generated

另外,此comb()函数还对字符串进行操作:

list( comb('catdogant', 3) )  # returns ['cat', 'dog', 'ant']

一种老式的方法,不需要itertools,但仍然可以使用任意生成器:

def chunks(g, n):
  """divide a generator 'g' into small chunks
  Yields:
    a chunk that has 'n' or less items
  """
  n = max(1, n)
  buff = []
  for item in g:
    buff.append(item)
    if len(buff) == n:
      yield buff
      buff = []
  if buff:
    yield buff
def main():
  print(chunkify([1,2,3,4,5,6],2))

def chunkify(list, n):
  chunks = []
  for i in range(0, len(list), n):
    chunks.append(list[i:i+n])
  return chunks

main()

我认为这很简单,可以为您提供数组的一部分。