user5740843
user5740843

Reputation: 1620

Python append lists in a specific way

I know that I can practically merge two list (in Python 2.7) as follows

list1 = ['one', 'two', 'three', 'four', 'five']
list2 = ['A', 'B', 'C', 'D', 'E']
merged = list1 + list2
print merged
# ['one', 'two', 'three', 'four', 'five', 'A', 'B', 'C', 'D', 'E']

The question is, I would like one of list2 inserted after every two of list1. Example:

list1 = ['one', 'two', 'three', 'four', 'five']
list2 = ['A', 'B', 'C', 'D', 'E']
after 2 of list1:
     add 1 of list2
print merged
# ['one', 'two', 'A', 'three', 'four', 'B', 'five', 'six', 'C', 'seven', 'eight', 'D', 'nine', 'ten']

Any help would be really appreciated!

Upvotes: 2

Views: 277

Answers (4)

akuiper
akuiper

Reputation: 215057

You can try izip_longest for python 2.7 (or zip_longest for python 3+), assuming extra elements from either of the lists will be appended to the result:

from itertools import izip_longest

[y for x in izip_longest(list1[::2], list1[1::2], list2) for y in x if y is not None]
# ['one', 'two', 'A', 'three', 'four', 'B', 'five', 'C', 'D', 'E']

Or use zip if you want to drop unpaired elements:

[y for x in zip(list1[::2], list1[1::2], list2) for y in x]
# ['one', 'two', 'A', 'three', 'four', 'B']

Upvotes: 3

Keerthana Prabhakaran
Keerthana Prabhakaran

Reputation: 3787

>>> from operator import add
>>> reduce(add,zip(list1[::2], list1[1::2], list2))
('one', 'two', 'A', 'three', 'four', 'B')

Caution - This will drop the trailing elements.

Explanation:

you can use list slicing like l as list l[low:high:step] to get,

>>> list1[::2]
['one', 'three', 'five']
>>> list1[1::2]
['two', 'four']

With that,

>>> zip(list1[::2], list1[1::2])
[('one', 'two'), ('three', 'four')]

Therefore,

>>> zip(list1[::2], list1[1::2], list2)
[('one', 'two', 'A'), ('three', 'four', 'B')]
>>> reduce(add,zip(list1[::2], list1[1::2], list2))
('one', 'two', 'A', 'three', 'four', 'B')

Upvotes: 1

Tadhg McDonald-Jensen
Tadhg McDonald-Jensen

Reputation: 21453

This is the kind of case where using a raw iterator makes for clean code, you can call next on an iterator to get the next value and then append it to the result so the list creation is quite intuitive:

list1 = ['one', 'two', 'three', 'four', 'five']
list2 = ['A', 'B', 'C', 'D', 'E']
iter_list1 = iter(list1)
iter_list2 = iter(list2)

final = []
try: #broken when one of the iterators runs out (and StopIteration is raised)
    while True:
        final.append(next(iter_list1))
        final.append(next(iter_list1))

        final.append(next(iter_list2))
except StopIteration:
    pass
#one will already be empty, add the remaining elements of the non-empty one to the end of the list.
final.extend(iter_list1)
final.extend(iter_list2)

print(final)

Upvotes: 6

MSeifert
MSeifert

Reputation: 152735

You could use enumerate and list.insert:

>>> l1 = ['A', 'B', 'C', 'D']
>>> l2 = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
>>> l3 = l2[:]  # makes a copy
>>> for idx, item in enumerate(l1):
...     l3.insert((idx*3+2), item)
>>> l3
['one', 'two', 'A', 'three', 'four', 'B', 'five', 'six', 'C', 'seven', 'eight', 'D', 'nine', 'ten']

Upvotes: 3

Related Questions