2015-04-03 6 views
3

Вот два списка, что я хочу, чтобы объединить и создать новый список:Объединить два списка, выбрав 2 элемента каждого

>>> 
>>> ls1 = [1, 2, 3, 4, 5] 
>>> ls2 = ['a', 'b', 'c', 'd'] 
>>> 

NB: два списка может быть разного размера.

Обязательный выход:

[(1, 2, 'a', 'b'), (3, 4, 'c', 'd'), (5)] 

Я попытался с помощью itertools.izip_longest, но не в состоянии достичь его:

>>> list(itertools.izip_longest(ls1, ls2)) 
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, None)] 
>>> 

Может некоторые-один бросить меня некоторый свет на это.

Благодаря

ответ

4

Как насчет старой доброй for?

result = [] 
for i in range(0, max(len(ls1),len(ls2)), 2): 
    result.append(tuple(ls1[i:i+2] + ls2[i:i+2])) 
+0

Это потрясающе :) –

+2

Как насчет старого доброго _list comprehension_ ?: 'Результат = [кортежей (LS1 [я: я + 2] + LS2 [я: я + 2]) для г в диапазоне (0, max (len (ls1), len (ls2)), 2)] ' – martineau

3

Вам нужно исправить последнюю запись (но вы можете сделать это довольно легко, потому что вы знаете длину ls1 и ls2).

>>> import itertools 
>>> ls1 = [1, 2, 3, 4, 5] 
>>> ls2 = ['a', 'b', 'c', 'd'] 
>>> list(itertools.izip_longest(ls1[0::2], ls1[1::2], ls2[0::2], ls2[1::2])) 
[(1, 2, 'a', 'b'), (3, 4, 'c', 'd'), (5, None, None, None)] 
1

Если вы не заботитесь о том, несколько дополнительных None, Вы не можете использовать iter с izip_longest чтобы избежать нарезку и создания новых списков:

ls1 = [1, 2, 3, 4, 5] 
ls2 = ['a', 'b', 'c', 'd'] 

it1 = iter(ls1) 
it2 = iter(ls2) 

zipped = izip_longest(it1, it1, it2, it2) 

print(list(zipped)) 
[(1, 2, 'a', 'b'), (3, 4, 'c', 'd'), (5, None, None, None)] 

Или использовать filter, чтобы удалить None's из последний кортеж:

from itertools import izip_longest 

ls1 = [1, 2, 3, 4, 5] 
ls2 = ['a', 'b', 'c', 'd'] 

it1 = iter(ls1) 
it2 = iter(ls2 
zipped = list(izip_longest(it1, it1, it2, it2)) 
zipped[-1] = tuple(filter(lambda x: x is not None, zipped[-1])) 
[(1, 2, 'a', 'b'), (3, 4, 'c', 'd'), (5,)] 

Для большого входа вы можете увидеть izip совсем немного более эффективным:

In [36]: ls1 = [1, 2, 3, 4, 5] * 1000000 
In [37]: ls2 = ['a', 'b', 'c', 'd'] * 1000000 
In [38]: %%timeit      
    it1 = iter(ls1) 
    it2 = iter(ls2) 
    zipped = list(izip_longest(it1, it1, it2, it2)) 
    zipped[-1] = tuple(filter(lambda x: x is not None, zipped[-1])) 
    ....: 
1 loops, best of 3: 224 ms per loop 

In [39]: %%timeit result = [] 
for i in xrange(0, max(len(ls1),len(ls2)), 2): 
    result.append(tuple(ls1[i:i+2] + ls2[i:i+2])) 
    ....: 
1 loops, best of 3: 1.46 s per loop 

In [40]: timeit list(itertools.izip_longest(ls1[0::2], ls1[1::2], ls2[0::2], ls2[1::2])) 
1 loops, best of 3: 404 ms per loop 

iter(ls1) создает итератор так проходящее it1, it1 означает, что мы пара каждые два элемента из списка, внутренне питон в основном движется указатель на следующий элемент каждый раз, когда мы итерацию над it1.

In [9]: ls2 = ['a', 'b', 'c', 'd']  
In [10]: it2 = iter(ls2)  
In [11]: next(it2), next(it2) # get first two elements 
Out[11]: ('a', 'b')  
In [12]: next(it2), next(it2) # again call next twice to get the 3rd and 4th elements 
Out[12]: ('c', 'd') 
+1

Это тоже очень хорошая идея. –

+0

не могли бы вы объяснить, как работает izip_longest вместе с итератором. –

+1

@sapam, я добавил пример внизу. Здесь есть хорошие примеры того, как они работают и как создавать собственные http://anandology.com/python-practice-book/iterators.html –

Смежные вопросы