1

Let's say I have multiple Python lists. What is one fast way to insert elements between the elements of the multiple Python lists?

# Have
list1 = [1, 2, 3]
list2 = [10, 11, 12]
list3 = [20, 21, 22]

# Expect
list_between = [1, 10, 20, 2, 11, 21, 3, 12, 22]
Yi Xiang Chong
  • 744
  • 11
  • 9

7 Answers7

6
list_between = [i for l in list(zip(list1, list2, list3)) for i in l] 

Just use zip and print the elements in order within the list of tuples using list comprehension.

list(zip(list1, list2, list3)) # returns [(1, 10, 20), (2, 11, 21), (3, 12, 22)]
Suraj
  • 2,253
  • 3
  • 17
  • 48
3

Pure python solution for arbitrary insertion

If you want to insert elements from listB into an arbitrary position in listA, there's the list.insert(index, object_to_insert) method.

If you're very concerned with speed, you should know that this probably won't be very fast because python lists are implemented as dynamic arrays, not linked lists. For faster insertion, you may want to implement your own linked list type.

Alternate numpy solution

If you want to combine three lists in exactly the way shown by your example, you can insert them into a numpy array and take the transpose of the array.

In [1]: import numpy as np

In [2]: listA = [1, 2, 3]
   ...: listB = [4, 5, 6]
   ...: listC = [7, 8, 9]
   ...:
   ...: arr = np.array([listA, listB, listC])
   ...: arr.T
Out[2]:
array([[1, 4, 7],
       [2, 5, 8],
       [3, 6, 9]])

In [3]: arr.T.flatten()
Out[3]: array([1, 4, 7, 2, 5, 8, 3, 6, 9])

In [4]: arr.T.flatten().tolist()
Out[4]: [1, 4, 7, 2, 5, 8, 3, 6, 9]
Emerson Harkin
  • 889
  • 5
  • 13
2

There is roundrobin in itertools.recipes, which do what you want:

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))

list1 = [1, 2, 3]
list2 = [10, 11, 12]
list3 = [20, 21, 22]

list_between = list(roundrobin(list1,list2,list3))
print(list_between)

Output:

[1, 10, 20, 2, 11, 21, 3, 12, 22]

Note that it also works for arguments of varying length (see docstring).

Daweo
  • 31,313
  • 3
  • 12
  • 25
  • Hi @Daweo thanks for sharing. I am new to programming so quite hard for me to understand do you mind explaining the code? – Yi Xiang Chong Jul 10 '20 at 14:43
  • @YiXiangChong: I fear that I am unable to do so clearly, I suggest looking for python iterators tutorials and then itertools module documentation. – Daweo Jul 10 '20 at 14:54
1

You can use :

import itertools

list(itertools.chain.from_iterable(zip(list1, list2, list3)))

If the lists do not have the same length, all lists will be shrinked to the length of the shortest one.

Gelineau
  • 2,031
  • 4
  • 20
  • 30
0

I'm not aware of any simple/fast ways, but if the example is representative where you want to essentially build up lists from multiple lists in this manner you could just do:

n = 3 # length of our lists, must all be the same for simple logic
our_lists = [list1, list2, list3]
new_list = []
for i in range(3):
    for l in our_lists:
        new_list.append(l[i])
Alexis Drakopoulos
  • 1,115
  • 7
  • 22
0

If all lists have the same number of elements you can use zip in a list comprehension:

list_between = [ e for e3 in zip(list1,list2,list3) for e in e3 ]
Alain T.
  • 40,517
  • 4
  • 31
  • 51
0

Here is a hacky way but slower compared to using np.transpose. This is achieved by inserting 0's in between the elements using slice and then adding the lists together:

# e.g.
# arr1 = [1, 0, 0, 2, 0, 0, 3, 0, 0]
# arr2 = [0, 1, 0, 0, 2, 0, 0, 3, 0]
# arr3 = [0, 0, 1, 0, 0, 2, 0, 0, 3]
#
# arr_ = [1, 1, 1, 2, 2, 2, 3, 3, 3] # use np.add to fast insert
 
list1 = np.insert(list1, slice(1, None, 1), 0) # create 0,0 paddings in between
list1 = np.insert(list1, slice(1, None, 2), 0)
list1 = np.insert(list1, 0, [0]*(0))
list1 = list1.tolist()
list1.extend([0]*(3-1))

list2 = np.insert(list2, slice(1, None, 1), 0)
list2 = np.insert(list2, slice(1, None, 2), 0)
list2 = np.insert(list2, 0, [0]*(0+1))
list2 = list2.tolist()
list2.extend([0]*(3-2))

list3 = np.insert(list3, slice(1, None, 1), 0)
list3 = np.insert(list3, slice(1, None, 2), 0)
list3 = np.insert(list3, 0, [0]*(0+2))
list3 = list3.tolist()
list3.extend([0]*(3-3))

list_ = np.add(list1, list2)
list_ = np.add(list_, list3)

list_
array([ 1, 10, 20,  2, 11, 21,  3, 12, 22])
Yi Xiang Chong
  • 744
  • 11
  • 9