2013-08-04 6 views
1

Учитывая два списка, я хочу объединить их так, чтобы все элементы из первого списка были проиндексированы с индексом (сохраняя их порядок), а все элементы из второго списка индексированы нечетно (также сохраняя их порядок). Пример ниже:python слияние двух списков (четные/нечетные элементы)

x = [0,1,2] 
y = [3,4] 

result = [0,3,1,4,2] 

Я могу сделать это, используя для петли. Но я думаю, что может быть фантастический питонический способ сделать это (используя менее известную функцию или что-то в этом роде). Есть ли лучшее решение для написания цикла?

Редактировать: Я думал о списках, но до сих пор не нашел решения.

+0

Что вы хотите сделать для 'х = [0,1,2,3,4,5,6]' 'но у = [20,21] ', или наоборот? (То есть, если один список намного длиннее или короче другого?) – torek

+0

предполагают более простой сценарий: len (x) == len (y) ИЛИ len (x) == len (y) + 1, Не волнуйся об этом. Это будет последовательность ходов для игры. – ducin

+0

В этом случае используйте «roundrobin», как показано ниже, или упрощенную версию. – torek

ответ

3

Вы можете просто сделать:

for i,v in enumerate(y): 
    x.insert(2*i+1,v) 

это имеет то преимущество, что вставка будет использовать последний индекс, когда он преодолен.

Один пример:

x = [0,1,2,3,4,5] 
y = [100, 11,22,33,44,55,66,77] 
print x 
# [0, 100, 1, 11, 2, 22, 3, 33, 4, 44, 5, 55, 66, 77] 
+2

Мне нравится это из-за его простоты - только для исправления не нужно изменять x. 'import copy' /' res = copy.copy (x) '/' для i, v в enumerate (y): '/'res.insert (2 * i + 1, v)' – ducin

+3

@tkoomzaaskz 'list.insert 'является операцией O (N). –

+0

@AshwiniChaudhary вы имеете в виду сложность? И что? (извините, если я не понял вашу точку) – ducin

7

Вот что вы можете использовать. (Используйте list(izip_longest(...)) для Py2x)

>>> from itertools import chain 
>>> from itertools import zip_longest 
>>> list(filter(lambda x: x != '', chain.from_iterable(zip_longest(x, y, fillvalue = '')))) 
[0, 3, 1, 4, 2] 

Это работает для произвольных списков длины нравится следующим образом -

>>> x = [0, 1, 2, 3, 4] 
>>> y = [5, 6] 
>>> list(filter(lambda x: x != '', chain.from_iterable(zip_longest(x, y, fillvalue = '')))) 
[0, 5, 1, 6, 2, 3, 4] 

Объяснение на нем работает -

  1. zip_longest(...) со значением заполнения молнии списки и заполняет заданное значение заполнения для повторений с неравной длиной. Итак, для вашего первоначального примера он оценивается примерно так: [(0, 3), (1, 4), (2, '')]
  2. Нам нужно сгладить результат, потому что этот метод дает нам список кортежей. Для этого мы используем chain.from_iterable(...), давая нам что-то вроде [0, 3, 1, 4, 2, ''].
  3. Теперь мы используем filter(...), чтобы удалить все записи '', и мы получим требуемый ответ.
+0

для len (x) = len (y) +1: 'list (chain.from_iterable (zip (x, y))) + [x [-1]] ' – Muposat

4

Попробуйте это:

x = [0,1,2,10,11] 
y = [3,4] 

n = 2*max([len(x),len(y)]) 
res = n *[None] 
res[:2*len(x):2] = x 
res[1:2*len(y):2] = y 
res = [x for x in res if x!=None] 
print res 

Она должна работать неравномерно длинных списков.

5

Используйте roundrobinrecipe из itertools:

from itertools import cycle, islice 
def roundrobin(*iterables): 
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C" 
    # Recipe credited to George Sakkis 
    pending = len(iterables) 
    nexts = cycle(iter(it).next for it in iterables) 
    while pending: 
     try: 
      for next in nexts: 
       yield next() 
     except StopIteration: 
      pending -= 1 
      nexts = cycle(islice(nexts, pending)) 
>>> list(roundrobin(x,y)) 
[0, 3, 1, 4, 2] 
2

Это достаточно просто, хотя и не столь гибки, как roundrobin:

def paired(it1, it2): 
    it2 = iter(it2) 
    for item in it1: 
     yield item 
     yield next(it2) 

испытания в 2.7.5:

>>> x = [0, 1, 2] 
>>> y = [3, 4] 
>>> print list(paired(x, y)) 
[0, 3, 1, 4, 2] 

Обратите внимание, что он останавливается как только список y закончится (потому что next(it2) вызывает StopIteration).

+0

yep, но - как я писал в вопросе - я могу сделать это, используя только цикл for. Я думал о чем-то основанном на синтаксисе (например, о разрезе списков или списках). В любом случае, спасибо – ducin

+0

Это пропустит несколько элементов: 'парный (y, x)'. –

+0

@AshwiniChaudhary: вот почему я спросил выше, что делать, когда один список длиннее другого. – torek

3

Если у вас есть одинаковые списки длины, вы можете использовать это:

result = [ item for tup in zip(x,y) for item in tup ] 
1

Это может быть сделано с нарезку. У count и slice в терминале:

>>> list1=['Apple','Mango','Orange'] 
>>> list2=['One','Two','Three'] 
>>> list = [None]*(len(list1)+len(list2)) 
>>> list[::2] = list1 
>>> list[1::2] = list2 
>>> list 

Выход:

['Apple', 'One', 'Mango', 'Two', 'Orange', 'Three']