通过选择每个2元素合并两个列表

时间:2015-04-03 00:31:34

标签: python list itertools

以下是我要合并并创建新列表的两个列表:

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

注意:两个列表的大小可能不同。

必填项:

[(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)]
>>>

有些人可以对我说些什么。

谢谢

3 个答案:

答案 0 :(得分: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]))

答案 1 :(得分:3)

您需要修复最后一个条目(但您可以相当轻松地完成此操作,因为您知道ls1ls2的长度。

>>> 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)]

答案 2 :(得分:1)

如果您不在乎多少额外的无,则可以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意味着我们将对列表中的每两个元素进行配对,内部python基本上每次迭代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')