2016-10-18 4 views
1

У меня есть три списка с элементами:поочередно добавляющие элементы из двух списков

a = [[0,1],[2,3],...] 
b = [[5,6],[7,8],...] 

c = [] 

Я хочу, чтобы добавить элементы из и б в с получить:

c = [ [0,1],[5,6],[2,3],[7,8],.... ] 
+2

Вы имеете в виду '[5,6]' вместо '[5,3]'? –

+1

Что делать, если списки не имеют одинаковой длины? – jbndlr

+0

Вы хотите добавить элементы из списков 'a' и' b' по очереди? – Nurjan

ответ

2

Еще один очень простой подход с использованием строки нарезкинаиболее производительность эффективной) как:

>>> a = [[0,1],[2,3]] 
>>> b = [[5,6],[7,8]] 
>>> c = a + b # create a list with size = len(a) + len(b) 
>>> c[::2], c[1::2] = a, b # alternately insert the value 
>>> c 
[[0, 1], [5, 6], [2, 3], [7, 8]] 

Ниже приводится сравнение результатов с timeit для ответов, упомянутых здесь (Python версия: 2.7):

  1. Используя строку нарезки: 0,586 мксек за петлю

    [email protected]:~$ python -m "timeit" -s "a = [[0,1],[2,3]]; b = [[5,6],[7,8]];" "c = a + b; c[::2], c[1::2] = a, b" 
    1000000 loops, best of 3: 0.586 usec per loop 
    
  2. Использование itertools.chain(): 1,89 мксек за петли

    [email protected]:~$ python -m "timeit" -s "from itertools import chain; a = [[0,1],[2,3]]; b = [[5,6],[7,8]];" "c = list(chain(*zip(a, b)))" 
    1000000 loops, best of 3: 1.89 usec per loop 
    
  3. Использование reduce(): 0,829 мксек за петли

  4. Использование list.extend(): 0,824 мксек на петле

    [email protected]:~$ python -m "timeit" -s "a = [[0,1],[2,3]]; b = [[5,6],[7,8]]; c=[]" "for pair in zip(a,b): c.extend(pair)" 
    1000000 loops, best of 3: 0.824 usec per loop 
    
  5. Использование list.append() дважды: 1,04 мксек на петле

    [email protected]:~$ python -m "timeit" -s "a = [[0,1],[2,3]]; b = [[5,6],[7,8]]; c=[]" "for a_element, b_element in zip(a, b): c.append(a_element); c.append(b_element)" 
    1000000 loops, best of 3: 1.04 usec per loop 
    
+0

Хорошо. Но вы действительно должны передавать 'timeit' эти инструкции установки с помощью опции' -s'. FWIW, в Python 3.6 моя '[* цепочка (* zip (a, b))]' примерно на 10% быстрее, чем моя версия «list (chain ...)», а мой список comp немного быстрее этого. –

+0

@ PM2Ring: Да, вы правы. Я пропустил это. Обновлен ответ. –

+1

@ PM2Ring: Я использую 'Python 2.7', поэтому не смог оценить его для упомянутого вами синтаксиса. Но я уже упомянул в своем ответе, что моя оценка для 'Python 2.7' –

6

Основной подход:

>>> a = [[0,1],[2,3]] 
>>> b = [[5,6],[7,8]] 
>>> c = [] 
>>> for pair in zip(a,b): 
... c.extend(pair) 
... 
>>> c 
[[0, 1], [5, 6], [2, 3], [7, 8]] 
>>> 

Это разрывается, если длины не равны. Но вы можете заниматься этим делом в качестве упражнения.

1

Рассмотрим:

merged = [] 
for a_element, b_element in zip(a, b): 
    merged.append(a_element) 
    merged.append(b_element) 

Если у вас очень жесткие требования к производительности, самый простой подход является правильным подходом.

2

Вы можете zip два списка, а затем свести их к плоскому листу:

import operator 
c = reduce(operator.concat, zip(a, b)) 
0

Предполагая LEN (а) == Len (б) и вы добавляете их один за другим, в свою очередь:

for i in range(len(a)): 
     c.append(a[i]) 
     c.append(b[i]) 

Однако я бы рекомендовал использовать c = deque(). Поскольку deques намного быстрее, если вы делаете много добавок.

+0

Выберите свой код и нажмите CTRL + K, чтобы отформатировать его правильно. –

+0

Сложнее отправить код с смартфона. – Nurjan

+0

Ну ладно, я думаю, вы просто отступили в каждой строке с четырьмя пробелами. –

2

Предполагая, что два списка имеют одинаковую длину, самый компактный способ для этого использует itertools.chain и zip.

from itertools import chain 

a = [[0,1],[2,3],[10,11],[12,13]] 
b = [[5,6],[7,8],[15,16],[17,18]] 

c = [*chain(*zip(a, b))] 
print(c) 

выход

[[0, 1], [5, 6], [2, 3], [7, 8], [10, 11], [15, 16], [12, 13], [17, 18]] 

Как juanpa.arrivillaga упоминает в комментариях, что синтаксис не будет работать на старых версиях Python. Вместо этого, вы можете сделать

c = list(chain(*zip(a, b))) 

Вот еще один вариант, который не использует импорт или оператор * пейнтбольный:

c = [u for t in zip(a, b) for u in t] 

Если вам нужно обрабатывать входные списки разной длины, принимать посмотрите на функцию roundrobin в Itertools Recipes. Например,

c = list(roundrobin(a, b)) 
+0

Я думаю, вы имеете в виду 'list (chain (* zip (a, b)))' хотя я вроде * хочу * этот синтаксис был поддержан. –

+0

@ juanpa.arrivillaga Код, который я написал для меня на Python 3.6. Но я думаю, что лучше добавить старый синтаксис к моему ответу. –

+0

О! Я должен начать делать больше желаний! –

1

Использование more_itertools который реализует itertoolsroundrobin recipe

>>> from more_itertools import roundrobin 
>>> a = [[0,1],[2,3]] 
>>> b = [[5,6],[7,8]] 
>>> list(roundrobin(a, b)) 
[[0, 1], [5, 6], [2, 3], [7, 8]] 
Смежные вопросы