interleaving 2 lists of unequal lengths [duplicate]

Solution 1:

You can use itertools.izip_longest here:

>>> from itertools import izip_longest
>>> xs = [1,2,3]
>>> ys = ["hi","bye","no","yes","why"]
>>> s = object()
>>> [y for x in izip_longest(xs, ys, fillvalue=s) for y in x if y is not s]
[1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']

Using roundrobin recipe from itertools, no sentinel value required here:

from itertools import *
def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

Demo:

>>> list(roundrobin(xs, ys))
[1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']
>>> list(roundrobin(ys, xs))
['hi', 1, 'bye', 2, 'no', 3, 'yes', 'why']

Solution 2:

You can use heapq.merge:

xs = [1, 2, 3]
ys = ['hi', 'bye', 'no', 'yes', 'why']

import heapq
interleaved = [v for i, v in heapq.merge(*[enumerate(el) for el in (xs, ys)])]
# [1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']

This avoids the need for a sentinel value and flattening.

Use the roundrobin recipe instead to achieve this more effectively without having items be comparable.

Solution 3:

Okay, here's my entry:

>>> from itertools import chain
>>> xs = [1,2,3]
>>> ys = ["hi","bye","no","yes","why"]
>>> xi, yi = iter(xs), iter(ys)
>>> list(chain.from_iterable(zip(xi, yi))) + list(xi) + list(yi)
[1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why']

Alternatively,

>>> [i for row in zip(xi, yi) for i in row] + list(xi) + list(yi)

would have worked too (that's just the listcomp idiom for flattening, as used by @hcwhsa). My first thought was

>>> list(zip(*sorted(list(enumerate(xs)) + list(enumerate(ys)))))[1]
(1, 'hi', 2, 'bye', 3, 'no', 'yes', 'why')

but that's just a much less efficient version of @Jon Clements (I used an inefficient sort, he used an efficient heap queue.)

[I've been experimenting trying to get something using cycle working, but it doesn't seem to be as easy as I'd hoped: and it turns out that I was simply working toward reimplementing the roundrobin recipe that @hcwsha posted, so there's no point in finishing that. :^) ]