22

I want interleave 4 lists of same length in python.

I search this site and only see how to interleave 2 in python: Interleaving two lists in Python

Can give advice for 4 lists?

I have lists like this

l1 = ["a","b","c","d"]
l2 = [1,2,3,4]
l3 = ["w","x","y","z"]
l4 = [5,6,7,8]

I want list like

l5 = ["a",1,"w",5,"b",2,"x",6,"c",3,"y",7,"d",4,"z",8]
机场之王
  • 263
  • 1
  • 4

7 Answers7

29

Provided the lists are the same length, zip() can be used to interleave four lists just like it was used for interleaving two in the question you linked:

>>> l1 = ["a", "b", "c", "d"]
>>> l2 = [1, 2, 3, 4]
>>> l3 = ["w", "x", "y", "z"]
>>> l4 = [5, 6, 7, 8]
>>> l5 = [x for y in zip(l1, l2, l3, l4) for x in y]
>>> l5
['a', 1, 'w', 5, 'b', 2, 'x', 6, 'c', 3, 'y', 7, 'd', 4, 'z', 8]
Sash Sinha
  • 18,743
  • 3
  • 23
  • 40
26

itertools.chain and zip:

from itertools import chain
l1 = ["a", "b", "c", "d"] l2 = [1, 2, 3, 4] l3 = ["w", "x", "y", "z"] l4 = [5, 6, 7, 8]
print(list(chain(*zip(l1, l2, l3, l4))))

Or as @PatrickHaugh suggested use chain.from_iterable:

list(chain.from_iterable(zip(l1, l2, l3, l4)))
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
Austin
  • 25,759
  • 4
  • 25
  • 48
10

From itertools recipes

The itertool recipes suggest a solution called roundrobin that allows for lists of different lengths.

from itertools import cycle, islice

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    num_active = len(iterables)
    nexts = cycle(iter(it).__next__ for it in iterables)
    while num_active:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            # Remove the iterator we just exhausted from the cycle.
            num_active -= 1
            nexts = cycle(islice(nexts, num_active))

print(*roundrobin(*lists)) # a 1 w 5 b 2 x 6 c 3 y 7 d 4 z 8

With slicing

Alternatively, here is a solution that relies solely on slicing, but requires that all lists be of equal lengths.

l1 = ["a","b","c","d"]
l2 = [1,2,3,4]
l3 = ["w","x","y","z"]
l4 = [5,6,7,8]

lists = [l1, l2, l3, l4]

lst = [None for _ in range(sum(len(l) for l in lists))]

for i, l in enumerate(lists):
    lst[i:len(lists)*len(l):len(lists)] = l

print(lst) # ['a', 1, 'w', 5, 'b', 2, 'x', 6, 'c', 3, 'y', 7, 'd', 4, 'z', 8]
Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73
6

For additional diversity (or for if you need to do this with Pandas)

import pandas as pd
l1 = ["a","b","c","d"]
l2 = [1,2,3,4]
l3 = ["w","x","y","z"]
l4 = [5,6,7,8]

df = pd.DataFrame([l1 ,l2, l3, l4])
result = list(df.values.flatten('A'))

['a', 1, 'w', 5, 'b', 2, 'x', 6, 'c', 3, 'y', 7, 'd', 4, 'z', 8]

Zev
  • 3,423
  • 1
  • 20
  • 41
5

Just for the sake of diversity, numpy.dstack and then flatten can do the same trick.

>>> import numpy as np
>>> l1 = ["a","b","c","d"]
>>> l2 = [1,2,3,4]
>>> l3 = ["w","x","y","z"]
>>> l4 = [5,6,7,8]
>>> np.dstack((np.array(l1),np.array(l2),np.array(l3),np.array(l4))).flatten()                                                                                                       
array(['a', '1', 'w', '5', 'b', '2', 'x', '6', 'c', '3', 'y', '7', 'd',                                                                                                              
       '4', 'z', '8'],                                                                                                                                                               
      dtype='|S21') 

BTW you actually don't need to make an array, the short version also works

>>> np.dstack((l1,l2,l3,l4)).flatten()                                                                                                       
array(['a', '1', 'w', '5', 'b', '2', 'x', '6', 'c', '3', 'y', '7', 'd',                                                                                                              
       '4', 'z', '8'],                                                                                                                                                               
      dtype='|S21')   
rth
  • 2,946
  • 1
  • 22
  • 27
4

One other way may be using zip with np.concatenate:

import numpy as np
l5 = np.concatenate(list(zip(l1, l2, l3, l4)))
print(l5)

Result:

['a' '1' 'w' '5' 'b' '2' 'x' '6' 'c' '3' 'y' '7' 'd' '4' 'z' '8']

Note: l5 is type numpy.ndarray, you can convert it to list either with list(l5) or l5.tolist()

niraj
  • 17,498
  • 4
  • 33
  • 48
2

Using zip and reduce:

import functools, operator
>>> functools.reduce(operator.add, zip(l1,l2,l3,l4))
('a', 1, 'w', 5, 'b', 2, 'x', 6, 'c', 3, 'y', 7, 'd', 4, 'z', 8)
emvee
  • 4,371
  • 23
  • 23