In Python, is there a good way to interleave two lists of the same length?
Say I\'m given [1,2,3]
and [10,20,30]
. I\'d like to transform th
Alternative:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> [y for x in map(None,l1,l2) for y in x if y is not None]
[1, 10, 2, 20, 3, 30]
This works because map works on lists in parallel. It works the same under 2.2. By itself, with None
as the called functions, map
produces a list of tuples:
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
Then just flatten the list of tuples.
The advantage, of course, is map
will work for any number of lists and will work even if they are different lengths:
>>> l1=[1,2,3]
>>> l2=[10,20,30]
>>> l3=[101,102,103,104]
>>> [y for x in map(None,l1,l2,l3) for y in x if y in not None]
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104]
Given
a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
Code
Assuming lists of equal length, you can get an interleaved list with itertools.chain
and zip
:
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
Alternatives
itertools.zip_longest
More generally with unequal lists, use zip_longest
(recommended):
[x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
# [1, 100, 2, 200, 3, 300, 999]
Many lists can safely be interleaved:
[x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
# [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
more_itertools+
A library that ships with the roundrobin itertools recipe, interleave and interleave_longest.
import more_itertools
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave_longest(a, c))
# [1, 100, 2, 200, 3, 300, 999]
yield from
Finally, for something interesting in Python 3 (though not recommended):
list(filter(None, ((yield from x) for x in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
list([(yield from x) for x in zip(a, b)])
# [1, 10, 2, 20, 3, 30]
+Install using pip install more_itertools
Having posted the question, I've realised that I can simply do the following:
[val for pair in zip(l1, l2) for val in pair]
where l1
and l2
are the two lists.
If there are N lists to interleave, then
lists = [l1, l2, ...]
[val for tup in zip(*lists) for val in tup]
Too late to the party, and there is plenty of good answers but I would also like to provide a simple solution using extend()
method:
list1 = [1, 2, 3]
list2 = [10, 20, 30]
new_list = []
for i in range(len(list1)):
new_list.extend([list1[i], list2[i]])
print(new_list)
Output:
[1, 10, 2, 20, 3, 30]
To answer the question's title of "Interleave multiple lists of the same length in Python", we can generalize the 2-list answer of @ekhumoro. This explicitly requires that the lists are the same length, unlike the (elegant) solution by @NPE
import itertools
def interleave(lists):
"""Interleave a list of lists.
:param lists: List of lists; each inner length must be the same length.
:returns: interleaved single list
:rtype: list
"""
if len(set(len(_) for _ in lists)) > 1:
raise ValueError("Lists are not all the same length!")
joint = list(itertools.chain(*lists))
for l_idx, li in enumerate(lists):
joint[l_idx::len(lists)] = li
return joint
Examples:
>>> interleave([[0,2,4], [1, 3, 5]])
[0, 1, 2, 3, 4, 5]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12]])
[0, 1, 10, 2, 3, 11, 4, 5, 12]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14, 15]])
[0, 1, 10, 13, 2, 3, 11, 14, 4, 5, 12, 15]
>>> interleave([[0,2,4], [1, 3, 5], [10, 11, 12], [13, 14]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in interleave
ValueError: Lists are not all the same length!
>>> interleave([[0,2,4]])
[0, 2, 4]
For Python>=2.3, there's extended slice syntax:
>>> a = [0, 2, 4, 6, 8]
>>> b = [1, 3, 5, 7, 9]
>>> c = a + b
>>> c[::2] = a
>>> c[1::2] = b
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The line c = a + b
is used as a simple way to create a new list of exactly the right length (at this stage, its contents are not important). The next two lines do the actual work of interleaving a
and b
: the first one assigns the elements of a
to all the even-numbered indexes of c
; the second one assigns the elements of b
to all the odd-numbered indexes of c
.