Loop in a loop?

Paul Hankin paul.hankin at gmail.com
Thu Jan 17 18:59:44 EST 2008


On Jan 17, 7:02 pm, George Sakkis <george.sak... at gmail.com> wrote:
> On Jan 17, 12:25 pm, Paul Hankin <paul.han... at gmail.com> wrote:
>
>
>
> > On Jan 17, 4:38 pm, Bruno Desthuilliers <bruno.
>
> > 42.desthuilli... at wtf.websiteburo.oops.com> wrote:
> > > Now there are very certainly smart solutions using itertools, but the
> > > one I cooked is way too ugly so I'll leave this to itertools masters !-)
>
> > Here's my effort:
>
> > from itertools import izip, islice, chain, repeat
>
> > def padzip(*xs, **kw):
> >     pad = kw.get('padding', None)
> >     maxlen = max(len(x) for x in xs)
> >     return islice(izip(*[chain(x, repeat(pad)) for x in xs]), maxlen)
>
> > --
> > Paul Hankin
>
> And if the iterables don't necessarily support len(), here's a more
> general solution:
>
> from itertools import repeat
>
> def izippad(*iterables, **kw):
>     pad = kw.get('padding', None)
>     next_pad = repeat(pad).next
>     getnext = [iter(iterable).next for iterable in iterables]
>     pending = size = len(iterables)
>     while True:
>         slice = [None] * size
>         for i in xrange(size):
>             try: slice[i] = getnext[i]()
>             except StopIteration:
>                 pending -= 1
>                 if not pending: return
>                 getnext[i] = next_pad
>                 slice[i] = pad
>         yield slice

Instead of counting the exceptions, we can limit the padding iterables
by using an iterator that returns len(iterables) - 1 padding
generators, use a sort of lazy chain, and then just izip.

from itertools import izip, repeat

def chain_next(xs, yg):
    for x in xs: yield x
    for y in yg.next(): yield y

def izippad(*xs, **kw):
    padder = repeat(kw.get('padding', None))
    padder_gen = repeat(padder, len(xs) - 1)
    return izip(*[chain_next(x, padder_gen) for x in xs])

--
Paul Hankin




More information about the Python-list mailing list