[英]How to write a generator that returns ALL-BUT-LAST items in the iterable in Python?
I asked some similar questions [1, 2] yesterday and got great answers, but I am not yet technically skilled enough to write a generator of such sophistication myself. 昨天我问了一些类似的问题[1,2],并得到了很好的答案,但我在技术上还不够熟练,自己写出这样一个复杂的发电机。
How could I write a generator that would raise StopIteration if it's the last item, instead of yielding it? 如果它是最后一项,而不是让它产生,我怎么能写一个会引发StopIteration的生成器呢?
I am thinking I should somehow ask two values at a time, and see if the 2nd value is StopIteration. 我想我应该以某种方式一次询问两个值,看看第二个值是否为StopIteration。 If it is, then instead of yielding the first value, I should raise this StopIteration. 如果是,那么我应该提高这个StopIteration而不是产生第一个值。 But somehow I should also remember the 2nd value that I asked if it wasn't StopIteration. 但不知何故,我还应该记住,如果不是StopIteration,我会问第二个值。
I don't know how to write it myself. 我不知道怎么写自己。 Please help. 请帮忙。
For example, if the iterable is [1, 2, 3], then the generator should return 1 and 2. 例如,如果iterable是[1,2,3],那么生成器应该返回1和2。
Thanks, Boda Cydo. 谢谢,Boda Cydo。
[1] How do I modify a generator in Python? [1] 如何在Python中修改生成器?
[2] How to determine if the value is ONE-BUT-LAST in a Python generator? [2] 如何确定Python生成器中的值是否为1-BUT-LAST?
This should do the trick: 这应该做的伎俩:
def allbutlast(iterable):
it = iter(iterable)
current = it.next()
for i in it:
yield current
current = i
>>> list(allbutlast([1,2,3]))
[1, 2]
This will iterate through the entire list, and return the previous item so the last item is never returned. 这将迭代整个列表,并返回前一项,以便永远不会返回最后一项。
Note that calling the above on both [] and [1] will return an empty list. 请注意,在[]和[1]上调用上面的内容将返回一个空列表。
First off, is a generator really needed? 首先,真的需要一台发电机吗? This sounds like the perfect job for Python's slices syntax : 这听起来像Python的切片语法的完美工作:
result = my_range[ : -1]
Ie: take a range form the first item to the one before the last. 即:从第一个项目到最后一个项目的范围。
the itertools
module shows a pairwise()
method in its recipes. itertools
模块在其配方中显示了一个pairwise()
方法。 adapting from this recipe, you can get your generator: 根据这个配方,你可以得到你的发电机:
from itertools import *
def n_apart(iterable, n):
a,b = tee(iterable)
for count in range(n):
next(b)
return zip(a,b)
def all_but_n_last(iterable, n):
return (value for value,dummy in n_apart(iterable, n))
the n_apart()
function return pairs of values which are n elements apart in the input iterable, ignoring all pairs . n_apart()
函数返回值对,这些值在输入iterable中是n个元素,忽略所有对。 all_but_b_last()
returns the first value of all pairs, which incidentally ignores the n last elements of the list. all_but_b_last()
返回所有对的第一个值,偶然忽略列表的n个最后元素。
>>> data = range(10)
>>> list(data)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(n_apart(data,3))
[(0, 3), (1, 4), (2, 5), (3, 6), (4, 7), (5, 8), (6, 9)]
>>> list(all_but_n_last(data,3))
[0, 1, 2, 3, 4, 5, 6]
>>>
>>> list(all_but_n_last(data,1))
[0, 1, 2, 3, 4, 5, 6, 7, 8]
The more_itertools
project has a tool that emulates itertools.islice
with support for negative indices: more_itertools
项目有一个模拟itertools.islice
的工具,支持负索引:
import more_itertools as mit
list(mit.islice_extended([1, 2, 3], None, -1))
# [1, 2]
gen = (x for x in iterable[:-1])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.