最后获得带有附加项的成对迭代器
Get pairwise iterator with additional item in the end
目标:例如给定的有限迭代器 p0, p1, ..., pn
变成 (p0, p1), (p1, p2), ..., (pn-1, pn), (pn, None)
— 通过具有特殊最后一项的连续项目对的迭代器。
pairwise()
函数作为 itertools
用法的示例存在于文档中:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
但我还想在迭代器的末尾添加另一个项目(如果它是有限的),并为 pair 的第二个元素添加一些默认值(例如,None
)。
如何有效地实现这个附加功能?
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip_longest(a, b)
当其中一个输入迭代器用完时,zip_longest
用填充值填充它,默认为 None
。
至于在最后添加 (sn, None)
,正如 user2357112 已经回答的那样,您可以只使用 zip_longest
这样一个已经耗尽的迭代器就不会停止整个序列(所以 a
迭代器仍然可以产生最后一个元素)。
对于所有其他情况,例如如果你想在最后添加更多元素,你可以自己制作一个生成器函数。所有 itertools
函数都已经是惰性生成器,仅在您请求结果中的下一个元素时才产生新结果,并且您可以轻松地从生成器中使用这些结果。
比方说,你需要 pairwise
在最后产生一个标记值 (None, None)
,然后你可以简单地从 zip_longest
产生结果,然后产生另一个项目:
def example (iterable):
a, b = tee(iterable)
next(b, None)
yield from zip_longest(a, b)
yield (None, None)
yield from
语法实际上是 Python 3.3 附带的。对于早期版本,尤其是 Python 2,您需要通过遍历项目并再次生成它们来手动执行此操作:
def example (iterable):
a, b = tee(iterable)
next(b, None)
for x in zip_longest(a, b):
yield x
yield (None, None)
您可以创建一个生成器:
def pairwise(iterable, additional=None):
iterable = iter(iterable)
first, second = next(iterable), next(iterable)
while 1:
yield first,second
try:
first,second = second, next(iterable)
except TypeError:
yield second, additional
break
结果:
>>> list(pairwise([1,2,3], 'a'))
[(1, 2), (2, 3), (3, 'a')]
>>> list(pairwise('abc', 'a'))
[('a', 'b'), ('b', 'c'), ('c', 'a')]
>>> list(pairwise('abcd', 'a'))
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]
对于无限迭代:
>>> a = pairwise(infi(), 6)
>>> for i in range(10):
... print(next(a))
...
(0, 1)
(1, 2)
(2, 3)
(3, 0)
(0, 1)
(1, 2)
(2, 3)
(3, 0)
(0, 1)
(1, 2)
目标:例如给定的有限迭代器 p0, p1, ..., pn
变成 (p0, p1), (p1, p2), ..., (pn-1, pn), (pn, None)
— 通过具有特殊最后一项的连续项目对的迭代器。
pairwise()
函数作为 itertools
用法的示例存在于文档中:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
但我还想在迭代器的末尾添加另一个项目(如果它是有限的),并为 pair 的第二个元素添加一些默认值(例如,None
)。
如何有效地实现这个附加功能?
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip_longest(a, b)
当其中一个输入迭代器用完时,zip_longest
用填充值填充它,默认为 None
。
至于在最后添加 (sn, None)
,正如 user2357112 已经回答的那样,您可以只使用 zip_longest
这样一个已经耗尽的迭代器就不会停止整个序列(所以 a
迭代器仍然可以产生最后一个元素)。
对于所有其他情况,例如如果你想在最后添加更多元素,你可以自己制作一个生成器函数。所有 itertools
函数都已经是惰性生成器,仅在您请求结果中的下一个元素时才产生新结果,并且您可以轻松地从生成器中使用这些结果。
比方说,你需要 pairwise
在最后产生一个标记值 (None, None)
,然后你可以简单地从 zip_longest
产生结果,然后产生另一个项目:
def example (iterable):
a, b = tee(iterable)
next(b, None)
yield from zip_longest(a, b)
yield (None, None)
yield from
语法实际上是 Python 3.3 附带的。对于早期版本,尤其是 Python 2,您需要通过遍历项目并再次生成它们来手动执行此操作:
def example (iterable):
a, b = tee(iterable)
next(b, None)
for x in zip_longest(a, b):
yield x
yield (None, None)
您可以创建一个生成器:
def pairwise(iterable, additional=None):
iterable = iter(iterable)
first, second = next(iterable), next(iterable)
while 1:
yield first,second
try:
first,second = second, next(iterable)
except TypeError:
yield second, additional
break
结果:
>>> list(pairwise([1,2,3], 'a'))
[(1, 2), (2, 3), (3, 'a')]
>>> list(pairwise('abc', 'a'))
[('a', 'b'), ('b', 'c'), ('c', 'a')]
>>> list(pairwise('abcd', 'a'))
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')]
对于无限迭代:
>>> a = pairwise(infi(), 6)
>>> for i in range(10):
... print(next(a))
...
(0, 1)
(1, 2)
(2, 3)
(3, 0)
(0, 1)
(1, 2)
(2, 3)
(3, 0)
(0, 1)
(1, 2)