# How to interleave two lists of different length?

## Question:

I want to write a function `twolists` which gives results like:

``````outcome = twolists([ ], ['w', 'x', 'y', 'z'])
print(outcome)
['w', 'x', 'y', 'z']

outcome = twolists([0, 1], ['w', 'x'])
print(outcome)
[0, 'w', 1, 'x']

outcome = twolists([0, 1], ['w', 'x', 'y', 'z'])
print(outcome)
[0, 'w', 1, 'x', 'y', 'z']

outcome = twolists([0, 1, 2, 3], ['w', 'x'])
print(outcome)
[0, 'w', 1, 'x', 2, 3]
``````

I have this so far:

``````def twolists(list1, list2): # don't forget to return final_list
alt_list = []
a1 = len(list1)
a2 = len(list2)

for i in range(# ? ):
# append one thing from list1 to alt_list - How?
# append one thing from list2 to alt_list - How?
``````

How can I complete the code?

If you instead want to intersperse elements from the shorter list with roughly even spacing, see How to elegantly interleave two lists of uneven length in python?.

This composes a list comprehension using `zip_longest` from itertools (which is part of the standard library) to interleave items from both lists into a `tuple`, which by default uses `None` as the fillvalue.

This also uses `chain` also from `itertools` to flatten the list.

Finally it filters the `None` items from the list:

``````from itertools import chain, zip_longest
def twolists(l1, l2):
return [x for x in chain(*zip_longest(l1, l2)) if x is not None]
``````

Or as recommended from @EliKorvigo, use `itertools.chain.from_iterable` for iterating lazily:

``````def twolists(l1, l2):
return [x for x in chain.from_iterable(zip_longest(l1, l2)) if x is not None]
``````

Testing

``````In [56]: twolists([0, 1], ['w', 'x'])
Out[56]: [0, 'w', 1, 'x']

In [57]: twolists([0, 1], ['w', 'x', 'y', 'z'])
Out[57]: [0, 'w', 1, 'x', 'y', 'z']

In [74]: twolists([0, 1, 2, 3], ['w', 'x'])
Out[74]: [0, 'w', 1, 'x', 2, 3]
``````
``````def twolists(list1, list2):
newlist = []
a1 = len(list1)
a2 = len(list2)

for i in range(max(a1, a2)):
if i < a1:
newlist.append(list1[i])
if i < a2:
newlist.append(list2[i])

return newlist
``````

Here’s a solution that deals in iterators. The advantage to this is that it will work with any iterable data structure, not just lists.

``````def twolists(list1, list2):
result = []
iter1 = iter(list1)
iter2 = iter(list2)
try:
while True:
result.append(next(iter1))
result.append(next(iter2))
except StopIteration:
# This exception will be raised when either of the iterators
# hits the end of the sequence.
pass
# One of the lists is exhausted, but not both of them. We need
# to finish exhausting the lists.
try:
while True:
result.append(next(iter1))
except StopIteration:
pass
try:
while True:
result.append(next(iter2))
except StopIteration:
pass
return result
``````

If you don’t care whether your original lists (`a` and `b` in the following example) change, you can use the following snippet:

``````def twolists(a, b):
result = []
while len(a) > 0:
result.append(a.pop(0))
if len(b) > 0:
result.append(b.pop(0))
result += a + b
return result

twolists([ ], ['w', 'x', 'y', 'z'])
print(outcome)

outcome = twolists([0, 1], ['w', 'x'])
print(outcome)

outcome = twolists([0, 1], ['w', 'x', 'y', 'z'])
print(outcome)

outcome = twolists([0, 1, 2, 3], ['w', 'x'])
print(outcome)
``````

Produces the following output:

``````['w', 'x', 'y', 'z']
[0, 'w', 1, 'x']
[0, 'w', 1, 'x', 'y', 'z']
[0, 'w', 1, 'x', 2, 3]
``````

A basic approach:

You could `zip()` the lists normally, and append the rest of the biggest list if both lists are not the same size:

``````def two_lists(lst1, lst2):
result = []

for pair in zip(lst1, lst2):
result.extend(pair)

if len(lst1) != len(lst2):
lsts = [lst1, lst2]
smallest = min(lsts, key = len)
biggest = max(lsts, key = len)
rest = biggest[len(smallest):]
result.extend(rest)

return result
``````

Which works as follows:

``````>>> print(two_lists([], ['w', 'x', 'y', 'z']))
['w', 'x', 'y', 'z']
>>> print(two_lists([0, 1], ['w', 'x']))
[0, 'w', 1, 'x']
>>> print(two_lists([0, 1], ['w', 'x', 'y', 'z']))
[0, 'w', 1, 'x', 'y', 'z']
>>> print(two_lists([0, 1, 2, 3], ['w', 'x']))
[0, 'w', 1, 'x', 2, 3]
``````

Another possible approach:

You could also use `collections.deque` to convert the lists to `deque()` objects beforehand, and pop off the beginning of each one with `popleft()`, until one of the objects is empty. Then you could append the rest of the list that is not yet empty.

Here is an example:

``````def two_lists2(lst1, lst2):
result = []

fst, snd = deque(lst1), deque(lst2)

while fst and snd:
result.append(fst.popleft())
result.append(snd.popleft())

rest = leftover(fst, snd)
if rest:
result.extend(rest)

return result

def leftover(x, y):
if x and not y:
return x

elif y and not x:
return y

return None
``````

Note: Both of the approaches are `O(n)` time, which is expected for this kind of problem.

``````def CombineLists(lst1, lst2):
return [item for x in zip(lst1,lst2) for item in x] + /
(lst2[len(lst1):] if len(lst2)>len(lst1) else lst1[len(lst2):])
``````
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.