如何编写一个生成器,在Python中的iterable中返回ALL-BUT-LAST项?

时间:2010-03-11 13:11:19

标签: python

昨天我问了一些类似的问题[1,2]并得到了很好的答案,但我在技术上还不够熟练,自己写一个这样复杂的发电机。

如果它是最后一项而不是让它产生,我怎么能写一个会引发StopIteration的生成器呢?

我想我应该以某种方式一次询问两个值,看看第二个值是否为StopIteration。如果是,那么我应该提高这个StopIteration而不是产生第一个值。但不知何故,我还应该记住,如果不是StopIteration,我会问第二个值。

我不知道怎么写自己。请帮忙。

例如,如果iterable是[1,2,3],那么生成器应该返回1和2.

谢谢,Boda Cydo。

[1] How do I modify a generator in Python?

[2] How to determine if the value is ONE-BUT-LAST in a Python generator?

5 个答案:

答案 0 :(得分:12)

这应该可以解决问题:

def allbutlast(iterable):
    it = iter(iterable)
    current = it.next()
    for i in it:
        yield current
        current = i


>>> list(allbutlast([1,2,3]))
[1, 2]

这将遍历整个列表,并返回上一个项目,以便永远不会返回最后一个项目 请注意,在[]和[1]上调用上面的内容将返回一个空列表。

答案 1 :(得分:2)

首先,真的需要一台发电机吗?这听起来像是Python slices syntax的完美工作:

result = my_range[ : -1]

即:从第一个项目到最后一个项目的范围。

答案 2 :(得分:1)

itertools模块在​​其配方中显示pairwise()方法。根据这个配方,你可以得到你的发电机:

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))

n_apart()函数返回值对,它们在输入可迭代中是n个元素,忽略所有对。 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]

答案 3 :(得分:0)

more_itertools项目有一个模拟itertools.islice的工具,支持负面索引:

import more_itertools as mit

list(mit.islice_extended([1, 2, 3], None, -1))
# [1, 2]

答案 4 :(得分:-2)

gen = (x for x in iterable[:-1])