Могу ли я "склеить" содержимое итератора в свой собственный итератор на Python? - PullRequest
2 голосов
/ 23 февраля 2011

Предположим, у меня есть итератор, и я хочу добавить некоторые элементы до или после него. Единственный способ сделать это - использовать явный цикл:

def myiter(other_iter):
    yield "First element"
    for item in other_iter:
        yield item
    yield "Last element"

Есть ли лучший или более эффективный способ сделать это? Есть ли функция с именем типа yield_items_from, которую можно использовать следующим образом?

def myiter(other_iter):
    yield "First element"
    yield_items_from(other_iter)
    yield "Last element"

Edit:

Хорошо, я упростил свой пример. Вот лучший вариант:

Предположим, у меня есть итератор other_iter, который возвращает возрастающую последовательность неотрицательных целых чисел. Я хочу вернуть итератор, который отсчитывает от нуля, возвращая 1 для чисел, возвращаемых other_iter, и 0 в противном случае. Например, если other_iter возвращает [1,4,5,7], я хочу получить [0,1,0,0,1,1,0,1]. Есть ли эффективный и читаемый способ сделать это?

Ответы [ 5 ]

3 голосов
/ 23 февраля 2011

Нет, нет ничего похожего на yield_items_from, хотя есть черновой вариант предложения добавить его в Python 3.X в PEP 380 .

Для текущего Python явный цикл - единственный способ получить результат от итератора. Тем не менее, это достаточно эффективно, и это идиоматический способ сделать это, поэтому вы не должны быть слишком обеспокоены многословием.

Если все, что вам нужно сделать, это добавить новые элементы в начало или конец итератора, то вы можете просто использовать <a href="http://docs.python.org/library/itertools.html#itertools.chain" rel="nofollow">itertools.chain</a> для создания нового итератора. Вы можете использовать его для объединения нескольких итераторов или добавлять / добавлять отдельные элементы, помещая их в список.

new_iter = itertools.chain(['prefix item'], old_iter, appended_iter)
2 голосов
/ 23 февраля 2011

Использование itertools.chain :

import itertools

for item in itertools.chain(["First element"],other_iter,["Last element"]):
    ...

По поводу отредактированного вопроса, как насчет:

import itertools as it

def bincounter(iterable):
    counter=it.count()
    for elt in iterable:
        for c in counter:
            if c < elt:
                yield 0
            else:
                yield 1
                break

other_iter=iter([1,4,5,7])    
print(list(bincounter(other_iter)))
# [0, 1, 0, 0, 1, 1, 0, 1]
0 голосов
/ 27 июня 2019

Начиная с Python 3.3, вы можете использовать синтаксическую форму yield from.

def myiter(other_iter):
    yield "First element"
    yield from other_iter
    yield "Last element"

См. PEP 380 - Синтаксис для делегирования субгенератору для подробностей или Что нового в Python 3.3 для краткого руководства.

0 голосов
/ 23 февраля 2011

Чтобы ответить на ваш новый вопрос:

other_iter = [1,4,5,7]

def flags( items ):
    c = 0
    for this in items:
        while c < this:
            yield 0
            c += 1
        yield 1

print list(flags(other_iter))

Я почти уверен, что нет встроенного или вспомогательного средства, которое делает это.

0 голосов
/ 23 февраля 2011

Itertools работает, но если вам нужен альтернативный вариант:

def ch(*iters):    
    for it in iters:
        for elem in it:
            yield elem    

s1=["First element"] 
s2=['middle 1', 'middle 2', 'middle 3']
s3=["last element"]

for i in ch(s1,s2,s3):
    print i

Обновление из вашего редактирования

Ваш конкретный запрос может быть удовлетворен:

def in_l(l):
    count = 0
    while count<=max(l):
        if count in l: 
            count += 1
            yield 1
        else: 
            count += 1
            yield 0   

print list(in_l([1,4,5,7]))

Помните, что l должна быть последовательностью, а не объектом-генератором.Последовательности имеют длину и макс.Генераторы могут быть бесконечными, и, следовательно, нет длины, нижний индекс, вычисляемого максимального значения.

Я думаю, что есть еще одна загадка?То, что вы описываете, звучит так, как будто есть много других шаблонов проектирования, которые лучше реализуют его.Вы смотрели на простой конечный автомат?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...