【问题标题】:Excluding the first element from an iterator (Python)从迭代器中排除第一个元素(Python)
【发布时间】:2018-12-28 01:02:38
【问题描述】:

我有一个生成器函数A

例如(实际上我有一个更复杂的函数A),

def A():
    yield from [i**2 for i in range(20)]

编写另一个生成器函数B,我想枚举A返回的所有元素,除了第一个元素。

在 Python 3 中简洁的实现方法有哪些?

【问题讨论】:

  • 显示 A 的代码
  • 使用next() ?
  • _, *rest = your_iterator
  • @dfundako:我试图完成您的请求(参见编辑后的代码),但是:a。 A() 有点太复杂了,b。 A() 还没有写:-)

标签: python python-3.x iterator


【解决方案1】:

通常,您不需要在表达式中使用它,因此您只需调用 next(it),忽略结果,使用并丢弃第一个元素。


但是,如果迭代器可能为空,您必须决定要发生什么:

  • 也许你想提高StopIteration,在这种情况下next(it) 很好。
  • 也许您想提出其他问题,在这种情况下,您将 next(it) 放在 except StopIteration: raise SomethingElse() 中。
  • 也许您只想将迭代器留空,在这种情况下您可以调用next(it, None)

您可以在标准库和文档中找到这些示例。例如,如果您浏览 itertools 中的食谱:

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

这正是您想要做的——跳过b 的第一个元素。如果iterable 是空的,你不希望这里出现错误;你只想迭代什么。所以,next(b, None)


如果您需要在表达式中间执行此操作怎么办?

然后你可以写一个跳过第一个元素的函数:

def skip_first(iterable):
    it = iter(iterable)
    next(it, None)
    return it

(同样,您必须决定要为空的可迭代对象发生什么。)

这将返回迭代器的第一个跳过版本,因此您可以内联使用它。 (当然,它会改变你传入的迭代器,但你通常只使用你没有保留任何引用的临时值,所以这不是问题。)

或者,如果您需要返回生成器而不是任意迭代器(通常不需要):

def skip_first(iterable):
    it = iter(iterable)
    next(it, None)
    yield from it

或者您可以使用相同想法的更通用版本,itertools.islice。以下具有相同的效果:

it = skip_first(it)
it = itertools.islice(it, 1, None)

虽然我们在使用 itertools 食谱,但值得一看 consume

def consume(iterator, n=None):
    "Advance the iterator n-steps ahead. If n is None, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

忘记None 部分;有趣的是,它跳过了带有islicenextn 元素。 (请注意,它正在原地变异 iterator,而不是返回任何东西。)

【讨论】:

    【解决方案2】:

    免责声明:请参阅上面的@abarnert 和@Solaxun 的答案。

    只是觉得应该提到以下几点

    如果你有例如original = iter((1,2,3,4,5))

    然后

    first, remaining = next(original), original
    

    其中remaining 是没有第一个元素的迭代器。


    【讨论】:

      【解决方案3】:

      使用itertools.islice:

      itertools.islice(generator,1,None)
      

      【讨论】:

      • 感谢您的评论.. 正在自己更新。这种方法与 first, *rest = generator 等其他方法之间的区别在于,这将保留生成器的惰性(而不是预先消耗整个事物)。
      猜你喜欢
      • 1970-01-01
      • 2016-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-23
      • 2013-02-20
      • 2013-01-05
      相关资源
      最近更新 更多