通过每个选择 2 个元素来合并两个列表
Merge two list by selecting 2 element each
这是我要合并并创建一个新列表的两个列表:
>>>
>>> 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)]
>>>
谁能给我一些启发。
谢谢
您需要修复最后一个条目(但您可以很容易地做到这一点,因为您知道 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)]
一个好的旧 for
循环怎么样?
result = []
for i in range(0, max(len(ls1),len(ls2)), 2):
result.append(tuple(ls1[i:i+2] + ls2[i:i+2]))
如果您不关心有几个额外的 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
意味着我们将对列表中的每两个元素进行配对,内部 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')
这是我要合并并创建一个新列表的两个列表:
>>>
>>> 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)]
>>>
谁能给我一些启发。
谢谢
您需要修复最后一个条目(但您可以很容易地做到这一点,因为您知道 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)]
一个好的旧 for
循环怎么样?
result = []
for i in range(0, max(len(ls1),len(ls2)), 2):
result.append(tuple(ls1[i:i+2] + ls2[i:i+2]))
如果您不关心有几个额外的 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
意味着我们将对列表中的每两个元素进行配对,内部 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')