Turn the twin generator upside down

I have a generator similar to the itertools recipe pairwisethat gives (s0,s1), (s1,s2), (s2, s3).... I want to create another generator from it, which will give the original sequence 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

How to write unpairas a generator without resorting to lists?

+4
source share
5 answers

May be:

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

It should be:

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

If you are concerned about what ifis evaluated in each cycle, you can of course:

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

You can try the following:

def unpair(iterable):
    it = iter(iterable)
    head = next(it)
    yield head[0]
    yield head[1]
    for fst, snd in it:
        yield snd
+2
source
>>> from itertools import chain
>>> def unpair(iterable):
...     x, y = zip(*iterable)
...     return chain([x[0]], y)
+1
source

DSM version which is short but works for an empty list:

from itertools import islice, chain
def unpair(iterable):
    p = iter(iterable)
    return chain(chain(*islice(p,1)),(x[1] for x in p))
+1
source

All Articles