我试图创建一个自定义函数来改进itertools的pairwise函数。
不像pairwise函数,它返回对的项目(n = 2),我希望能够指定分组长度(n = x),这样我就可以返回指定长度的项目组,这可能吗?
所以当n=2
时,groupwise函数应该等价于itertools pairwise函数,但是当n=3
时,我希望它返回3个一组的结果。
这就是我目前所知道的--它本质上与成对函数相同。即适用于n = 2。
代码:
from itertools import tee
my_string = 'abcdef'
def groupwise(iterable, n):
a = tee(iterable, n)
next(a[n-1], None)
return zip(a[0], a[1])
for item in groupwise(my_string, 2):
print("".join(item))
输出:
ab
bc
cd
de
ef
我试图修改上面的代码以接受n=3, n=4, n=5, ... n=x
,但是考虑到我想指定n <= len(my_string)
的任何值,我想不出一种方法来为zip函数提供不确定数量的组件
- 当n = 3时,输出应为:**
abc
bcd
cde
def
1条答案
按热度按时间jjjwad0x1#
不幸的是,
tee
不会以这种方式扩展,编写pairwise
需要一次tee
调用,如果要对每个组中的N个元素执行此操作,则需要N-1次tee
调用。幸运的是,我们可以通过自己滚动循环来做得更好。我们要做的是跟踪我们自己看到的最后N个元素,每当我们有一个足够大的组时,就对它们执行
yield
。为此,我们需要一个数据结构,它可以有效地向右添加元素,并从左减去元素。collections.deque
会做得很好。事实上,它甚至有一个maxlen
参数,当我们需要它的时候,它会 * 自动 * 从左边减去。构造一个空的双端队列(第一个构造函数参数是初始元素:一个空元组),其容量为
n
。当我们在右侧添加超过n
的元素时,它会自动删除最左侧的元素。我们可以手动完成此操作,但deque
会为我们完成此操作,因此我们还不如利用它们提供的功能。然后迭代可迭代对象,将每个元素附加到双端队列的末尾(根据需要从左开始,以满足最大长度要求),然后,如果双端队列有
n
个元素,我们就对它进行yield
,这使得我们的函数成为generator function,因此它将产生一个新的迭代器,该迭代器包含所有yield
ed值。我们制作了一个deque的浅副本,这样我们就不会每次都产生相同的(可变的)deque对象,我们还制作了一个
tuple
的浅副本,而不是一个deque,以便与其他itertools
功能更一致。要调用,请使用