The most comprehensive way to mix two lists in python

Suppose there are 2 lists

l1 = [1, 2, 3] l2 = [a, b, c, d, e, f, g...] 

result:

 list = [1, a, 2, b, 3, c, d, e, f, g...] 

You cannot use zip() because it reduces the result to the smallest list . I also need a list on the output, not an iterable .

+8
python list
source share
7 answers
 >>> l1 = [1,2,3] >>> l2 = ['a','b','c','d','e','f','g'] >>> [i for i in itertools.chain(*itertools.izip_longest(l1,l2)) if i is not None] [1, 'a', 2, 'b', 3, 'c', 'd', 'e', 'f', 'g'] 

To allow the inclusion of None values ​​in lists, you can use the following modification:

 >>> from itertools import chain, izip_longest >>> l1 = [1, None, 2, 3] >>> l2 = ['a','b','c','d','e','f','g'] >>> sentinel = object() >>> [i for i in chain(*izip_longest(l1, l2, fillvalue=sentinel)) if i is not sentinel] [1, 'a', None, 'b', 2, 'c', 3, 'd', 'e', 'f', 'g'] 
+10
source share

Another possibility ...

 [y for x in izip_longest(l1, l2) for y in x if y is not None] 

(after importing izip_longest from itertools, of course)

+7
source share

The easiest way to do this is to use the recipe specified in the itertools docs :

 def roundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> ADEBFC" # 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)) 

What can be used like this:

 >>> l1 = [1,2,3] >>> l2 = ["a", "b", "c", "d", "e", "f", "g"] >>> list(roundrobin(l1, l2)) [1, 'a', 2, 'b', 3, 'c', 'd', 'e', 'f', 'g'] 

Note that 2.x requires a slightly different version of roundrobin , introduced in the 2.x docs .

This also avoids the problem that the zip_longest() method has, that lists can contain None without deleting it.

+2
source share
 minLen = len(l1) if len(l1) < len(l2) else len(l2) for i in range(0, minLen): list[2*i] = l1[i] list[2*i+1] = l2[i] list[i*2+2:] = l1[i+1:] if len(l1) > len(l2) else l2[i+1:] 

this is not a shortcut, but it removes unnecessary dependencies.

update: here is another way suggested by @jsvk

 mixed = [] for i in range( len(min(l1, l2)) ): mixed.append(l1[i]) mixed.append(l2[i]) list += max(l1, l2)[i+1:] 
+1
source share

If you need output in a single list, instead of a list of tuples, try this.

 Out=[] [(Out.extend(i) for i in (itertools.izip_longest(l1,l2))] Out=filter(None, Out) 
0
source share

I am not saying that this is the best way to do this, but I just wanted to point out that you can use zip:

 b = zip(l1, l2) a = [] [a.extend(i) for i in b] a.extend(max([l1, l2], key=len)[len(b):]) >>> a [1, 'a', 2, 'b', 3, 'c', 'd', 'e', 'f', 'g'] 
0
source share
 >>> a = [1, 2, 3] >>> b = list("abcdefg") >>> [x for e in zip(a, b) for x in e] + b[len(a):] [1, 'a', 2, 'b', 3, 'c', 'd', 'e', 'f', 'g'] 
0
source share

All Articles