你能想出一个很好的方法(可能用itertools)将迭代器拆分成给定大小的块吗?
因此l=[1,2,3,4,5,6,7]与chunks(l,3)变成一个迭代[1,2,3], [4,5,6], [7]
我可以想到一个小程序来做这个,但不是一个很好的方式可能itertools.
Sve*_*ach 126
在grouper() 从配方itertools文件的食谱来靠近你想要什么:
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
Run Code Online (Sandbox Code Playgroud)
不过,它会用填充值填充最后一个块.
一种不太通用的解决方案,仅适用于序列,但可以根据需要处理最后一个块
[my_list[i:i + chunk_size] for i in range(0, len(my_list), chunk_size)]
Run Code Online (Sandbox Code Playgroud)
最后,对一般迭代器起作用的解决方案的行为符合要求
def grouper(n, iterable):
it = iter(iterable)
while True:
chunk = tuple(itertools.islice(it, n))
if not chunk:
return
yield chunk
Run Code Online (Sandbox Code Playgroud)
rec*_*dev 52
虽然OP要求函数将块返回为列表或元组,但是如果需要返回迭代器,则可以修改Sven Marnach的解决方案:
def grouper_it(n, iterable):
it = iter(iterable)
while True:
chunk_it = itertools.islice(it, n)
try:
first_el = next(chunk_it)
except StopIteration:
return
yield itertools.chain((first_el,), chunk_it)
Run Code Online (Sandbox Code Playgroud)
一些基准测试:http://pastebin.com/YkKFvm8b
只有当你的函数遍历每个块中的元素时,它才会稍微高效一些.
Mik*_*ike 30
Python 3.12 添加了itertools.batched,它适用于所有可迭代对象(包括列表):
>>> from itertools import batched
>>> for batch in batched('ABCDEFG', 3):
... print(batch)
('A', 'B', 'C')
('D', 'E', 'F')
('G',)
Run Code Online (Sandbox Code Playgroud)
Céd*_*YER 22
从 python 3.8 开始,有一个使用:=运算符的更简单的解决方案:
def grouper(iterator: Iterator, n: int) -> Iterator[list]:
while chunk := list(itertools.islice(iterator, n)):
yield chunk
Run Code Online (Sandbox Code Playgroud)
然后这样称呼它:
>>> list(grouper(iter('ABCDEFG'), 3))
[['A', 'B', 'C'], ['D', 'E', 'F'], ['G']]
Run Code Online (Sandbox Code Playgroud)
注意:您可以放入iter函数grouper以取 anIterable而不是Iterator。
小智 12
这适用于任何可迭代的.它返回发电机的发电机(充分灵活).我现在意识到它与@reclosedevs解决方案基本相同,但没有绒毛.无需try...except为StopIteration传播了起来,这是我们想要的.
在next(iterable)需要调用,以提高StopIteration当迭代是空的,因为islice将永远继续下去产卵空的发电机,如果你让它.
它更好,因为它只有两行,但很容易理解.
def grouper(iterable, n):
while True:
yield itertools.chain((next(iterable),), itertools.islice(iterable, n-1))
Run Code Online (Sandbox Code Playgroud)
请注意,它next(iterable)被放入元组中.否则,如果next(iterable)它本身是可迭代的,那么itertools.chain就会把它弄平.感谢Jeremy Brown指出这个问题.
我今天正在研究一些事情,想出了一个简单的解决方案.它类似于jsbueno的答案,但我相信group当长度iterable被整除时,他会产生空的n.我的答案在iterable疲惫时做了简单的检查.
def chunk(iterable, chunk_size):
"""Generate sequences of `chunk_size` elements from `iterable`."""
iterable = iter(iterable)
while True:
chunk = []
try:
for _ in range(chunk_size):
chunk.append(iterable.next())
yield chunk
except StopIteration:
if chunk:
yield chunk
break
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
47076 次 |
| 最近记录: |