分块迭代,包括生成器
Chunking iterables, including generators
我有这个用于分块迭代的解决方案:
def chunks(items, chunk_size):
def get_chunk():
try:
for _ in range(chunk_size):
yield next(iterator)
except StopIteration:
return False
iterator = iter(items)
while chunk := list(get_chunk()):
yield chunk
for c in chunks([1, 2, 3, 4, 5, 6, 7, 8], 3):
print(c)
它运行良好,与我在 SO 上找到的其他一些解决方案不同,它还处理 'infinite' 生成器,例如:
def natural_numbers():
n = 0
while True:
yield (n := n + 1)
tens = chunks(natural_numbers(), 10)
for _ in range(5):
print(next(tens))
但是,我无法动摇这样的感觉,即无需调用内部函数也可以做到这一点。当然,您可以定义一个外部函数并传入 chunk_size
和 iterator
,这将避免在每次调用 chunks
时重新定义 get_chunk()
。但是它仍然会有为每个块调用该函数的开销。
有没有人建议避免函数调用,但仍然适用于无法索引或切片的可迭代对象?
我使用该函数的主要原因是能够捕获 StopIteration
,我认为这不能在生成器理解中完成而不丢失异常前的最后几项,但也许我错了。
使用 while 循环:
def chunks(items, chunk_size):
iterator = iter(items)
done = False
while not done:
chunk = []
for _ in range(chunk_size):
try:
chunk.append(next(iterator))
except StopIteration:
done = True
break
if chunk:
yield chunk
使用 for 循环:
def chunks(items, chunk_size):
iterator = iter(items)
chunk = []
for element in iterator:
chunk.append(element)
if len(chunk) == chunk_size:
yield chunk
chunk = []
if chunk:
yield chunk
保留您的原始想法但删除嵌套函数:
from itertools import islice
def chunks(items, chunk_size):
iterator = iter(items)
while chunk := list(islice(iterator, chunk_size)):
yield chunk
使用第 3 方库:
>>> from more_itertools import chunked
>>> list(chunked([1, 2, 3, 4, 5, 6, 7, 8], 3))
[[1, 2, 3], [4, 5, 6], [7, 8]]
如果我没记错的话,more-itertools
有 chunked
和 ichunked
。
https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.chunked
我有这个用于分块迭代的解决方案:
def chunks(items, chunk_size):
def get_chunk():
try:
for _ in range(chunk_size):
yield next(iterator)
except StopIteration:
return False
iterator = iter(items)
while chunk := list(get_chunk()):
yield chunk
for c in chunks([1, 2, 3, 4, 5, 6, 7, 8], 3):
print(c)
它运行良好,与我在 SO 上找到的其他一些解决方案不同,它还处理 'infinite' 生成器,例如:
def natural_numbers():
n = 0
while True:
yield (n := n + 1)
tens = chunks(natural_numbers(), 10)
for _ in range(5):
print(next(tens))
但是,我无法动摇这样的感觉,即无需调用内部函数也可以做到这一点。当然,您可以定义一个外部函数并传入 chunk_size
和 iterator
,这将避免在每次调用 chunks
时重新定义 get_chunk()
。但是它仍然会有为每个块调用该函数的开销。
有没有人建议避免函数调用,但仍然适用于无法索引或切片的可迭代对象?
我使用该函数的主要原因是能够捕获 StopIteration
,我认为这不能在生成器理解中完成而不丢失异常前的最后几项,但也许我错了。
使用 while 循环:
def chunks(items, chunk_size):
iterator = iter(items)
done = False
while not done:
chunk = []
for _ in range(chunk_size):
try:
chunk.append(next(iterator))
except StopIteration:
done = True
break
if chunk:
yield chunk
使用 for 循环:
def chunks(items, chunk_size):
iterator = iter(items)
chunk = []
for element in iterator:
chunk.append(element)
if len(chunk) == chunk_size:
yield chunk
chunk = []
if chunk:
yield chunk
保留您的原始想法但删除嵌套函数:
from itertools import islice
def chunks(items, chunk_size):
iterator = iter(items)
while chunk := list(islice(iterator, chunk_size)):
yield chunk
使用第 3 方库:
>>> from more_itertools import chunked
>>> list(chunked([1, 2, 3, 4, 5, 6, 7, 8], 3))
[[1, 2, 3], [4, 5, 6], [7, 8]]
如果我没记错的话,more-itertools
有 chunked
和 ichunked
。
https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.chunked