2013-10-24 2 views
4

У меня есть генератор, похожий на рецепт itertools 'pairwise, который дает (s0,s1), (s1,s2), (s2, s3).... Я хочу создать из него еще один генератор, который даст исходную последовательность s0, s1, s2, s3,....Обратный «парный» генератор

from itertools import * 

def pairwise(iterable): 
    a, b = tee(iterable) 
    next(b, None) 
    return izip(a, b) 

a = [1,2,3,4] 

for item in unpair(pairwise(a)): 
    print item # should print 1,2,3,4 

Как написать unpair в качестве генератора, не прибегая к спискам?

+0

Почему вы должны сделать это? Можете ли вы дать больше контекста? –

ответ

5

Может быть:

def unpair(iterable): 
    p = iter(iterable) 
    return chain(next(p, []), (x[1] for x in p)) 
+1

Ничего, но как насчет края (пустой итерабельный)? – georg

+1

возвращает исключение - StopIteration - это именно то, что он должен вернуть, не так ли? –

+0

@CorleyBrigman Проблема в том, что он вызывает StopIteration уже при вызове, когда итерация еще не началась. Например, 'list (unair ([])) вызывает исключение вместо того, чтобы возвращать пустой список. –

3

Это должно быть это:

def unpairwise(iterable): 
    for i, (fst, snd) in enumerate(iterable): 
     if i == 0: 
      yield fst 
     yield snd 

Если вы обеспокоены if оценивается в каждом цикле, можно конечно сделать:

def unpairwise(iterable): 
    fst, snd = iterable.next() 
    yield fst 
    yield snd 
    for fst, snd in iterable: 
     yield snd 
+1

Хорошо, но я не доволен выражением 'if', выполняемым на каждой итерации, в то время как на самом деле это нужно только один раз. – georg

+0

@ thg435 Да, честно говоря, у меня тоже были проблемы ... Я включил версию без условия. Это менее элегантно для глаз, хотя. – vaab

1
>>> from itertools import chain 
>>> def unpair(iterable): 
...  x, y = zip(*iterable) 
...  return chain([x[0]], y) 
+0

Спасибо, но это, кажется, потребляет весь генератор заранее ... – georg

2

Вы можете t чень это:

def unpair(iterable): 
    it = iter(iterable) 
    head = next(it) 
    yield head[0] 
    yield head[1] 
    for fst, snd in it: 
     yield snd 
+0

На самом деле оказалось, что ваш код работает нормально с пустым генератором (так как, в отличие от DSM, это сам генератор). – georg

1

версия DSM, которая является кратким, но работает для пустого списка:

from itertools import islice, chain 
def unpair(iterable): 
    p = iter(iterable) 
    return chain(chain(*islice(p,1)),(x[1] for x in p)) 
Смежные вопросы