Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge lists in Python by placing every nth item from one list and others from another?

I have two lists, list1 and list2.

Here len(list2) << len(list1).

Now I want to merge both of the lists such that every nth element of final list is from list2 and the others from list1.

For example:

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

list2 = ['x', 'y']

n = 3

Now the final list should be:

['a', 'b', 'x', 'c', 'd', 'y', 'e', 'f', 'g', 'h']

What is the most Pythonic way to achieve this?

I want to add all elements of list2 to the final list, final list should include all elements from list1 and list2.

like image 774
ofnowhere Avatar asked Jan 09 '16 11:01

ofnowhere


People also ask

How do I merge a list into another list in Python?

In python, we can use the + operator to merge the contents of two lists into a new list. For example, We can use + operator to merge two lists i.e. It returned a new concatenated lists, which contains the contents of both list_1 and list_2.

How do I put multiple lists into one list?

Here, a for loop is used for adding the two lists using the append() method. This process is used as the append() method adds a single element to the end of a list. Thus, each element of the list2 is added to list1, one by one using the for loop.

How will you merge elements in a sequence in Python?

join() is an inbuilt string function in Python used to join elements of the sequence separated by a string separator. This function joins elements of a sequence and makes it a string.


Video Answer


4 Answers

Making the larger list an iterator makes it easy to take multiple elements for each element of the smaller list:

list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
list2 = ['x', 'y'] 
n = 3

iter1 = iter(list1)
res = []
for x in list2:
    res.extend([next(iter1) for _ in range(n - 1)])
    res.append(x)
res.extend(iter1)

>>> res
['a', 'b', 'x', 'c', 'd', 'y', 'e', 'f', 'g', 'h']

This avoids insert which can be expensive for large lists because each time the whole list needs to be re-created.

like image 163
Mike Müller Avatar answered Oct 09 '22 07:10

Mike Müller


To preserve the original list, you could try the following:

result = copy.deepcopy(list1)
index = n - 1
for elem in list2:
    result.insert(index, elem)
    index += n

result

['a', 'b', 'x', 'c', 'd', 'y', 'e', 'f', 'g', 'h']
like image 45
deborah-digges Avatar answered Oct 09 '22 07:10

deborah-digges


Using the itertools module and the supplementary more_itertools package, you can construct an iterable solution a couple different ways. First the imports:

import itertools as it, more_itertools as mt

This first one seems the cleanest, but it relies on more_itertools.chunked().

it.chain(*mt.roundrobin(mt.chunked(list1, n-1), list2))

This one uses only more_itertools.roundrobin(), whose implementation is taken from the itertools documentation, so if you don't have access to more_itertools you can just copy it yourself.

mt.roundrobin(*([iter(list1)]*(n-1) + [list2]))

Alternatively, this does nearly the same thing as the first sample without using any more_itertools-specific functions. Basically, grouper can replace chunked, but it will add Nones at the end in some cases, so I wrap it in it.takewhile to remove those. Naturally, if you are using this on lists which actually do contain None, it will stop once it reaches those elements, so be careful.

it.takewhile(lambda o: o is not None,
   it.chain(*mt.roundrobin(mt.grouper(n-1, list1), list2))
)

I tested these on Python 3.4, but I believe these code samples should also work in Python 2.7.

like image 38
David Z Avatar answered Oct 09 '22 06:10

David Z


What about the below solution? However I don't have a better one...

>>> list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> list2 = ['x', 'y']
>>> n = 2
>>> for i in range(len(list2)):
...     list1.insert(n, list2[i])
...     n += 3
...     
... 
>>> list1
['a', 'b', 'x', 'c', 'd', 'y', 'e', 'f', 'g', 'h']

n is 2 because the index of third element in a list is 2, since it starts at 0.

like image 42
Remi Crystal Avatar answered Oct 09 '22 08:10

Remi Crystal