Вопрос-Ответ

Pythonic way to combine (interleave, interlace, intertwine) two lists in an alternating fashion?

Питонический способ поочередного объединения (чередования, чересстрочной развертки, переплетения) двух списков?

У меня есть два списка, первый из которых гарантированно содержит ровно на один элемент больше, чем второй. Я хотел бы знать наиболее питонический способ создания нового списка, значения четного индекса которого берутся из первого списка, а значения нечетного индекса - из второго списка.

# example inputs
list1 = ['f', 'o', 'o']
list2 = ['hello', 'world']

# desired output
['f', 'hello', 'o', 'world', 'o']

Это работает, но не очень:

list3 = []
while True:
try:
list3.append(list1.pop(0))
list3.append(list2.pop(0))
except IndexError:
break

Как еще этого можно достичь? Какой подход является наиболее питоническим?


Если вам нужно обрабатывать списки разной длины (например, второй список длиннее или в первом более чем на один элемент больше, чем во втором), некоторые решения здесь будут работать, в то время как другие потребуют корректировки. Для получения более конкретных ответов смотрите Как чередовать два списка разной длины? оставить лишние элементы в конце или Как элегантно чередовать два списка разной длины? пытаться равномерно распределять элементы или вставлять элемент в список Python после каждого n-го элемента для случая, когда перед каждым "добавленным" элементом должно стоять определенное количество элементов.

Переведено автоматически
Ответ 1

Вот один из способов сделать это, разрезав:

>>> list1 = ['f', 'o', 'o']
>>> list2 = ['hello', 'world']
>>> result = [None]*(len(list1)+len(list2))
>>> result[::2] = list1
>>> result[1::2] = list2
>>> result
['f', 'hello', 'o', 'world', 'o']
Ответ 2

Рецепт для этого есть в itertools документации (примечание: для Python 3):

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))
Ответ 3
import itertools
print([x for x in itertools.chain.from_iterable(itertools.zip_longest(list1,list2)) if x])

Я думаю, что это самый питонический способ сделать это.

Ответ 4

В Python 2 это должно делать то, что вы хотите:

>>> iters = [iter(list1), iter(list2)]
>>> print list(it.next() for it in itertools.cycle(iters))
['f', 'hello', 'o', 'world', 'o']
python