Python将列表分割成n个块

59 投票
22 回答
148065 浏览
提问于 2025-04-18 11:32

我知道这个问题已经被讨论过很多次,但我的需求有点不同。

我有一个列表,比如说:range(1, 26)。我想把这个列表分成固定数量的部分,假设这个数量是 n,也就是 6。

>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
>>> l = [ x [i:i + 6] for i in range(0, len(x), 6) ]
>>> l
[[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24], [25]]

如你所见,我没有得到 6 个部分(六个子列表,每个子列表包含原列表的元素)。我想知道怎么才能把一个列表分成正好 n 个部分,这些部分可以是相等的,也可以是不相等的。

22 个回答

8

我想出了以下解决方案:

l = [x[i::n] for i in range(n)]

举个例子:

n = 6
x = list(range(26))

l = [x[i::n] for i in range(n)]
print(l)

输出结果:

[[0, 6, 12, 18, 24], [1, 7, 13, 19, 25], [2, 8, 14, 20], [3, 9, 15, 21], [4, 10, 16, 22], [5, 11, 17, 23]]

你可以看到,输出结果由 n 个部分组成,这些部分大致上有相同数量的元素。


这个是怎么实现的呢?

关键在于使用列表切片的步长(就是两个分号后面的数字),并且要逐步增加切片的起始位置。首先,从第一个元素开始,每隔 n 个取一个,然后从第二个元素开始,每隔 n 个取一个,依此类推。这样就完成了任务。

14

more_itertools.divide 是解决这个问题的一种方法:

import more_itertools as mit


iterable = range(1, 26)
[list(c) for c in mit.divide(6, iterable)]

输出结果

[[ 1,  2,  3,  4, 5],                       # remaining item
 [ 6,  7,  8,  9],
 [10, 11, 12, 13],
 [14, 15, 16, 17],
 [18, 19, 20, 21],
 [22, 23, 24, 25]]

如图所示,如果可迭代对象不能被均匀分割,剩下的项目会从第一个部分分配到最后一个部分。

想了解更多关于 more_itertools 库的信息,可以点击这里

37

如果顺序不重要:

def chunker_list(seq, size):
    return (seq[i::size] for i in range(size))

print(list(chunker_list([1, 2, 3, 4, 5], 2)))
>>> [[1, 3, 5], [2, 4]]

print(list(chunker_list([1, 2, 3, 4, 5], 3)))
>>> [[1, 4], [2, 5], [3]]

print(list(chunker_list([1, 2, 3, 4, 5], 4)))
>>> [[1, 5], [2], [3], [4]]

print(list(chunker_list([1, 2, 3, 4, 5], 5)))
>>> [[1], [2], [3], [4], [5]]

print(list(chunker_list([1, 2, 3, 4, 5], 6)))
>>> [[1], [2], [3], [4], [5], []]
51

下面的解决方案有很多优点:

  • 使用生成器来返回结果。
  • 不需要导入任何库。
  • 列表的大小是均衡的(比如把一个长度为17的列表分成5个列表时,不会出现4个列表大小为4,1个列表大小为1的情况)。
def chunks(l, n):
    """Yield n number of striped chunks from l."""
    for i in range(0, n):
        yield l[i::n]

上面的代码对于 l = range(16)n = 6 会产生以下输出:

[0, 6, 12]
[1, 7, 13]
[2, 8, 14]
[3, 9, 15]
[4, 10]
[5, 11]

如果你需要的分块是连续的,而不是交错的,可以使用这个:

def chunks(l, n):
    """Yield n number of sequential chunks from l."""
    d, r = divmod(len(l), n)
    for i in range(n):
        si = (d+1)*(i if i < r else r) + d*(0 if i < r else i - r)
        yield l[si:si+(d+1 if i < r else d)]

对于 l = range(16)n = 6,会产生:

[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9, 10, 11]
[12, 13]
[14, 15]

想了解生成器的更多优点,可以查看 这个stackoverflow链接

75

使用numpy

>>> import numpy
>>> x = range(25)
>>> l = numpy.array_split(numpy.array(x),6)

或者

>>> import numpy
>>> x = numpy.arange(25)
>>> l = numpy.array_split(x,6);

你也可以用numpy.split这个方法,但如果长度不能被整除,它会报错。

撰写回答