简体   繁体   English

从迭代器中排除第一个元素(Python)

[英]Excluding the first element from an iterator (Python)

I have a generator function A . 我有一个生成器函数A

For example (in reality I have a more complex function A ), 例如(实际上我有一个更复杂的函数A ),

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

Writing another generator function B , I want to enumerate all elements that A returns except the first element. 编写另一个生成器函数B ,我想枚举A返回的除第一个元素外的所有元素。

What are concise ways to implement this in Python 3? 在Python 3中有哪些简单的方法可以实现此目的?

使用itertools.islice

itertools.islice(generator,1,None)

Usually, you don't need this in an expression, so you just call next(it) , ignoring the results, to consume and discard the first element. 通常,您不需要在表达式中使用它,因此只需调用next(it)忽略结果,以消耗和丢弃第一个元素。


However, if the iterator might be empty, you have to decide what you want to happen: 但是,如果迭代器可能为空,则必须决定要发生的事情:

  • Maybe you want to raise StopIteration , in which case next(it) is fine. 也许您想提高StopIteration ,在这种情况next(it)很好。
  • Maybe you want to raise something else, in which case you next(it) inside an except StopIteration: raise SomethingElse() . 也许您想提出其他建议,在这种情况下,您next(it)except StopIteration: raise SomethingElse() next(it) except StopIteration: raise SomethingElse()
  • Maybe you just want to leave the iterator empty, in which case you can call next(it, None) . 也许您只是想让迭代器为空,在这种情况下,您可以调用next(it, None)

You can find examples of these in the stdlib and docs. 您可以在stdlib和docs中找到这些示例。 For example, if you scan through the recipes in itertools : 例如,如果您浏览itertools的配方:

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

This is doing exactly what you want to do—skip the first element of b . 这正是您想要做的—跳过b的第一个元素。 And if iterable is empty, you don't want an error here; 如果iterable为空,那么您就不要在这里出错了; you just want to iterate nothing. 您只想不进行任何迭代。 So, next(b, None) . 因此, next(b, None)


What if you need to do this in the middle of an expression? 如果您需要在表达式中间执行此操作怎么办?

Then you can write a function that skips the first element: 然后,您可以编写一个跳过第一个元素的函数:

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

(Again, you have to decide what you want to happen for an empty iterable.) (同样,您必须决定要为空的可迭代对象进行的操作。)

This returns a first-skipped version of the iterator, so you can use it inline. 这将返回迭代器的第一个跳过版本,因此您可以内联使用它。 (It also mutates the iterator you passed in, of course, but you normally only use on a temporary value that you're not keeping any references to, so that's not a problem.) (当然,它会使您传入的迭代器发生变化,但是您通常只使用不保留任何引用的临时值,所以这不是问题。)

Or, if you need to return a generator instead of an arbitrary iterator (usually you don't): 或者,如果您需要返回一个生成器而不是一个任意迭代器(通常不需要):

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

Or you can use the more general version of the same idea, itertools.islice . 或者,您可以使用相同想法的更通用版本itertools.islice The following have the same effect: 以下具有相同的效果:

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

While we're on the itertools recipes, it's worth looking at consume : 当我们使用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)

Forget the None part; 忘记“ None部分; the interesting bit is that it skips n elements with an islice and a next . 有趣的是,它会跳过带有islicenext n元素。 (Notice that it's mutating iterator in-place, not returning something.) (请注意,它是就地更改iterator ,而不返回任何内容。)

Disclaimer: See @abarnert and @Solaxun's answers above. 免责声明:请参阅上面的@abarnert和@Solaxun的答案。

Just thought that the following should be mentioned 只是认为应该提到以下几点

If you have eg original = iter((1,2,3,4,5)) 如果您有例如original = iter((1,2,3,4,5))

Then 然后

first, remaining = next(original), original

where remaining is the iterator without the first element. remaining是没有第一个元素的迭代器。


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM