# 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?.}

## Answers:

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):])
```