首页 > 解决方案 > Python中查找可迭代元素是否是最后一个的标准方法?

问题描述

如果我正在循环遍历 Python 的迭代器,我如何确定 now 是否是最后一个元素?我正在寻找一些标准库的方法,也许是一些函数itertools,有这样的吗?或者其他一些非常简短和 Pythonic 的方式来做到这一点。

当然,我可以实现自己的辅助生成器来完成此任务:

在线尝试!

def is_last(it):
    first = True
    for e in it:
        if not first:
            yield False, prev
        else:
            first = False
        prev = e
    if not first:
        yield True, prev

for last, e in is_last(range(4)):
    print(last, e)

哪个输出:

False 0
False 1
False 2
True 3

此外,如果我在简单范围内循环,我总是可以与上限进行比较(以下是正数的解决方案step):

在线尝试!

start, stop, step = 10, 21, 3
for i in range(start, stop, step):
    last = i + step >= stop
    print(last, i)

哪个输出:

False 10
False 13
False 16
True 19

对于简单范围的情况,上述这也是显而易见的并且可能是最简单的解决方案,不幸的是它需要将停止/步进保持在单独的变量中。但无论如何,范围案例并不是很有趣。任何任意迭代器的情况如何,是否有 Pythonic 的方法来解决这种情况?

标签: pythonloopsiterator

解决方案


我以前用过这样的东西。这不是一个很好的解决方案,因为它很容易被滥用,但它可以工作。

def peek(itr: Iterator[T]) -> Tuple[Optional[T], Optional[Iterator[T]]]:
    """
    Return a pair of (first element of iterator, new iterator).  If iterator is exhausted, return (None, None).
    https://stackoverflow.com/a/664239/3282436

    NOTE: Because checking for values consumes part of the supplied iterator, that iterator is invalidated.  To continue
          iterating, you *must* use the iterator returned from peek.

    >>> itr = iter(range(3))
    >>> if recipes.peek(itr)[0] == 0:  # WRONG, itr will be missing first element
    >>>     # ...

    >>> itr = iter(range(3))
    >>> first, itr = recipes.peek(itr)  # Correct
    >>> if first == 0:
    >>>     # ...
    """
    try:
        first = next(itr)
    except StopIteration:
        return None, None
    return first, itertools.chain([first], itr)

推荐阅读