Pythonic способ объединить два списка поочередно? - PullRequest
67 голосов
/ 09 сентября 2010

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

# 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

Как еще это может быть достигнуто? Какой самый питонский подход?

Ответы [ 18 ]

1 голос
/ 10 сентября 2010
def combine(list1, list2):
    lst = []
    len1 = len(list1)
    len2 = len(list2)

    for index in range( max(len1, len2) ):
        if index+1 <= len1:
            lst += [list1[index]]

        if index+1 <= len2:
            lst += [list2[index]]

    return lst
1 голос
/ 20 августа 2018

Может быть, немного поздно, купить еще один Python один вкладыш. Это работает, когда два списка имеют одинаковый или неравный размер. Одна вещь ничего не стоит, это изменит a и b. Если это проблема, вам нужно использовать другие решения.

a = ['f', 'o', 'o']
b = ['hello', 'world']
sum([[a.pop(0), b.pop(0)] for i in range(min(len(a), len(b)))],[])+a+b
['f', 'hello', 'o', 'world', 'o']
0 голосов
/ 10 апреля 2019

Как насчет NumPy? Он также работает со строками:

import numpy as np

np.array([[a,b] for a,b in zip([1,2,3],[2,3,4,5,6])]).ravel()

Результат:

array([1, 2, 2, 3, 3, 4])
0 голосов
/ 10 августа 2016

Несколько строк, вдохновленных ответами на другой вопрос :

import itertools

list(itertools.chain.from_iterable(itertools.izip_longest(list1, list2, fillvalue=object)))[:-1]

[i for l in itertools.izip_longest(list1, list2, fillvalue=object) for i in l if i is not object]

[item for sublist in map(None, list1, list2) for item in sublist][:-1]
0 голосов
/ 09 сентября 2010

Я бы сделал простое:

chain.from_iterable( izip( list1, list2 ) )

Он создаст итератор без каких-либо дополнительных требований к хранилищу.

0 голосов
/ 17 мая 2013

Это неприятно, но работает независимо от размера списков:

list3 = [element for element in list(itertools.chain.from_iterable([val for val in itertools.izip_longest(list1, list2)])) if element != None]
0 голосов
/ 09 сентября 2010

Я слишком стар, чтобы не понимать списки, поэтому:

import operator
list3 = reduce(operator.add, zip(list1, list2))
0 голосов
/ 09 сентября 2010

Остановки на самые короткие:

def interlace(*iters, next = next) -> collections.Iterable:
    """
    interlace(i1, i2, ..., in) -> (
        i1-0, i2-0, ..., in-0,
        i1-1, i2-1, ..., in-1,
        .
        .
        .
        i1-n, i2-n, ..., in-n,
    )
    """
    return map(next, cycle([iter(x) for x in iters]))

Конечно, разрешение метода next / __ next__ может быть быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...