Как написать генератор, который возвращает элементы ALL-BUT-LAST в итерируемых в Python? - PullRequest
4 голосов
/ 11 марта 2010

Вчера я задал несколько похожих вопросов [1, 2] и получил отличные ответы, но у меня пока недостаточно технических навыков, чтобы написать генератор такой изощренности.

Как я мог бы написать генератор, который бы вызывал StopIteration, если это последний элемент, вместо того, чтобы давать его?

Я думаю, что мне нужно как-то спросить два значения за раз и посмотреть, является ли 2-е значение StopItered. Если это так, то вместо того, чтобы выдавать первое значение, я должен поднять этот StopItered. Но почему-то я должен также вспомнить 2-е значение, которое я спросил, не было ли это StopIteration.

Я не знаю, как написать это сам. Пожалуйста, помогите.

Например, если итерация равна [1, 2, 3], то генератор должен вернуть 1 и 2.

Спасибо, Бода Цидо.

[1] Как изменить генератор в Python?

[2] Как определить, является ли значение ONE-BUT-LAST в генераторе Python?

Ответы [ 5 ]

12 голосов
/ 11 марта 2010

Это должно сработать:

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] вернет пустой список.

2 голосов
/ 11 марта 2010

Прежде всего, действительно ли нужен генератор? Это звучит как идеальная работа для синтаксиса Python :

result = my_range[ : -1]

Т.е.: взять диапазон от первого элемента до предыдущего.

1 голос
/ 11 марта 2010

модуль 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]
0 голосов
/ 14 июня 2017

В проекте more_itertools есть инструмент, эмулирующий itertools.islice с поддержкой отрицательных индексов:

import more_itertools as mit

list(mit.islice_extended([1, 2, 3], None, -1))
# [1, 2]
0 голосов
/ 11 марта 2010
gen = (x for x in iterable[:-1])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...