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. :^) ]