如何将任意长度的列表拆分为大小相等的块?
请参阅如果数据结果将直接用于循环,并且不需要存储,则如何以块形式遍历列表。
对于字符串输入的同一问题,请参见每n个字符拆分字符串?。相同的技术通常适用,但也有一些变化。
如何将任意长度的列表拆分为大小相等的块?
请参阅如果数据结果将直接用于循环,并且不需要存储,则如何以块形式遍历列表。
对于字符串输入的同一问题,请参见每n个字符拆分字符串?。相同的技术通常适用,但也有一些变化。
当前回答
我专门为此写了一个小图书馆,这里有。库的分块函数特别有效,因为它是作为生成器实现的,因此在某些情况下可以节省大量内存。它也不依赖切片表示法,因此可以使用任意迭代器。
import iterlib
print list(iterlib.chunked(xrange(1, 1000), 10))
# prints [(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (11, 12, 13, 14, 15, 16, 17, 18, 19, 20), ...]
其他回答
senderle答案的一个线性版本:
from itertools import islice
from functools import partial
seq = [1,2,3,4,5,6,7]
size = 3
result = list(iter(partial(lambda it: tuple(islice(it, size)), iter(seq)), ()))
assert result == [(1, 2, 3), (4, 5, 6), (7,)]
用户@tzot的解决方案zip_langest(*[iter(lst)]*n,fillvalue=padvalue)非常优雅,但如果lst的长度不能被n整除,它会填充最后一个子列表,以保持其长度与其他子列表的长度匹配。然而,如果这不可取,那么只需使用zip()生成类似的循环zip,并将lst的剩余元素(不能生成“完整”子列表)附加到输出即可。
输出示例为ABCDEFG,3->ABC DEF G。
单线版本(Python>=3.8):
list(map(list, zip(*[iter(lst)]*n))) + ([rest] if (rest:=lst[len(lst)//n*n : ]) else [])
A函数:
def chunkify(lst, chunk_size):
nested = list(map(list, zip(*[iter(lst)]*chunk_size)))
rest = lst[len(lst)//chunk_size*chunk_size: ]
if rest:
nested.append(rest)
return nested
生成器(尽管每个批次都是一个元组):
def chunkify(lst, chunk_size):
for tup in zip(*[iter(lst)]*chunk_size):
yield tup
rest = tuple(lst[len(lst)//chunk_size*chunk_size: ])
if rest:
yield rest
它比这里的一些最流行的答案产生相同的输出更快。
my_list, n = list(range(1_000_000)), 12
%timeit list(chunks(my_list, n)) # @Ned_Batchelder
# 36.4 ms ± 1.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit [my_list[i:i+n] for i in range(0, len(my_list), n)] # @Ned_Batchelder
# 34.6 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit it = iter(my_list); list(iter(lambda: list(islice(it, n)), [])) # @senderle
# 60.6 ms ± 5.36 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(mit.chunked(my_list, n)) # @pylang
# 59.4 ms ± 4.92 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit chunkify(my_list, n)
# 25.8 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
同样,从Python 3.12开始,这个功能将作为itertools模块中的批处理方法来实现(目前是一个配方),因此这个答案很可能会被Python 3.12淘汰。
没有魔力,但简单而正确:
def chunks(iterable, n):
"""Yield successive n-sized chunks from iterable."""
values = []
for i, item in enumerate(iterable, 1):
values.append(item)
if i % n == 0:
yield values
values = []
if values:
yield values
def chunk(input, size):
return map(None, *([iter(input)] * size))
您可以使用numpy的array_split函数,例如np.array_split(np.array(data),20),将其拆分为20个大小几乎相等的块。
要确保块的大小完全相等,请使用np.split。