最后获取带有附加项的成对迭代器

Posted

技术标签:

【中文标题】最后获取带有附加项的成对迭代器【英文标题】:Get pairwise iterator with additional item in the end 【发布时间】:2016-01-02 03:18:12 【问题描述】:

目标:例如给定有限迭代器 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)

但我还想在迭代器的末尾添加另一个项目(如果它是有限的),并为对的第二个元素(例如,None)添加一些默认值。

如何有效地实现这个附加功能?

【问题讨论】:

【参考方案1】:

使用itertools.zip_longest

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

【讨论】:

【参考方案2】:

至于在末尾添加(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)

【讨论】:

【参考方案3】:

你可以创建一个生成器:

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)

【讨论】:

以上是关于最后获取带有附加项的成对迭代器的主要内容,如果未能解决你的问题,请参考以下文章

枚举器和迭代器

python -- 迭代器

31 迭代器 Iterator 是什么?

python迭代器

迭代器

java集合之迭代器