iterator 从迭代器中产生 n 元组作为 oneliner 表达式

问题描述 投票:0回答:1

我要找的是

Itertools Recipes
的代码部分中描述的函数batched(iterable, n) 的单线变体,它将把数据批处理成一定长度的元组。

假设源是任意长度的迭代器,例如对 sys.stdin 的迭代,它在我的用例中接收字符串。

最后,我想要一个生成器,它产生一定长度的元组,最后一个元组也可能更短(取决于项目的总数)。

AFAIK,

batched(iterable, n)
将在将于今年晚些时候发布的 Python 3.12 中实现,但我想了解当前版本的 oneliner 解决方案的外观。

这是我到目前为止想出的(例如元组长度为 2):

from itertools import islice, zip_longest

foo=('aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff', 'ggg',) ## for simulating sys.stdin

# a oneliner that gets close but would fill lacking elements with None, so
# list(slicepairs0) would be [('aaa', 'bbb'), ('ccc', 'ddd'), ('eee', 'fff'), ('ggg', None)]
slicepairs0 = zip_longest(*[iter(foo)]*2)

# a oneliner that gets close but ignores possibly remaining elements, so
# list(slicepairs1) would be [('aaa', 'bbb'), ('ccc', 'ddd'), ('eee', 'fff')]
slicepairs1 = zip(*[iter(foo)]*2)

# a function similar to how batched() is currently implemented
def giveslicepair(foo):
  fooi=iter(foo)
  while nextslice := tuple(islice(fooi,2)):
    yield nextslice

# this iterator does what it should but relies on the generator-funtion giveslicepair(), so
# list(slicepairs2) would be [('aaa', 'bbb'), ('ccc', 'ddd'), ('eee', 'fff'), ('ggg',)]
slicepairs2 = ( item for item in giveslicepair(foo) )

我尝试将 giveslicepair() 的功能体现到最后一行的迭代器表达式中,但无法使其正常工作。感觉我在这里忽略了一些明显的东西,并感谢提示如何以高性能和 pythonic 方式执行此操作。

旁注:在现实世界的应用中,元组的大小通常预计在 50 到 400 左右,而不是只有 2 个。输入的行数可能相差很大,可以是 1 到数十亿之间的任何值。

python generator one-liner
1个回答
0
投票

如果你想要一个班轮,你可以使用

iter()
lambda
参数:

from itertools import islice

def one_line_batched(iterable, n):
    return iter(lambda it=iter(iterable): tuple(islice(it, n)), tuple())

print(list(one_line_batched('ABCDEFG', 3)))

印花:

[('A', 'B', 'C'), ('D', 'E', 'F'), ('G',)]
© www.soinside.com 2019 - 2024. All rights reserved.