[英]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: 但是,如果迭代器可能为空,则必须决定要发生的事情:
StopIteration
, in which case next(it)
is fine. 也许您想提高StopIteration
,在这种情况next(it)
很好。 next(it)
inside an except StopIteration: raise SomethingElse()
. 也许您想提出其他建议,在这种情况下,您next(it)
在except StopIteration: raise SomethingElse()
next(it)
except StopIteration: raise SomethingElse()
。 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
. 有趣的是,它会跳过带有islice
和next
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.