Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way to mix two lists

Tags:

python

I have two lists of length n and n+1:

[a_1, a_2, ..., a_n]
[b_1, b_2, ..., b_(n+1)]

I want a function giving as a result a list with alternate elements from the two, that is

[b_1, a_1, ..., b_n, a_n, b_(n+1)]

The following works, but does not look smart:

def list_mixing(list_long,list_short):
    list_res = []
    for i in range(len(list_short)):
        list_res.extend([list_long[i], list_short[i]])
    list_res.append(list_long[-1])
    return list_res

Can anyone suggest a more pythonic way of doing this? Thanks!

like image 843
Giulia Avatar asked Sep 23 '11 13:09

Giulia


2 Answers

>>> import itertools
>>> a
['1', '2', '3', '4', '5', '6']
>>> b
['a', 'b', 'c', 'd', 'e', 'f']
>>> list(itertools.chain.from_iterable(zip(a,b)))
['1', 'a', '2', 'b', '3', 'c', '4', 'd', '5', 'e', '6', 'f']

zip() produces a iterable with the length of shortest argument. You can either append a[-1] to the result, or use itertools.zip_longest(izip_longest for Python 2.x) with a fill value and delete that value afterwards.

And you can use more than two input sequences with this solution.

For not appending the last value, you can try this dirty approach, but I don't really recommend it, it isn't clear:

>>> a
[1, 2, 3, 4, 5]
>>> b
['a', 'b', 'c', 'd', 'e', 'f']
>>> [a[i//2] if i%2 else b[i//2] for i in range(len(a)*2+1)]
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f']

(For Python 2.x, use single /)

like image 180
utdemir Avatar answered Nov 02 '22 00:11

utdemir


more-itertools has roundrobin which exactly does the job:

from more_itertools import roundrobin

l1 = [1, 3, 5]
l2 = [2, 4, 6, 8, 10]

print(list(roundrobin(l1,l2)))
# [1, 2, 1, 3, 4, 3, 5, 6, 5, 8, 10]
like image 34
wrznr Avatar answered Nov 02 '22 02:11

wrznr