我有两个清单
a = [1,2,3]
b = [9,10]
我想将这两个列表合并(压缩)到一个列表中c
,这样
c = [(1,9), (2,10), (3, )]
Python的标准库中是否有任何功能可以做到这一点?
我有两个清单
a = [1,2,3]
b = [9,10]
我想将这两个列表合并(压缩)到一个列表中c
,这样
c = [(1,9), (2,10), (3, )]
Python的标准库中是否有任何功能可以做到这一点?
通常,您itertools.zip_longest
用于此:
>>> import itertools
>>> a = [1, 2, 3]
>>> b = [9, 10]
>>> for i in itertools.zip_longest(a, b): print(i)
...
(1, 9)
(2, 10)
(3, None)
但是用 s (或您作为参数传递的任何值)zip_longest
填充较短的可迭代对象。如果这不是您想要的,那么您可以使用理解来过滤掉s:None
fillvalue=
None
>>> for i in (tuple(p for p in pair if p is not None)
... for pair in itertools.zip_longest(a, b)):
... print(i)
...
(1, 9)
(2, 10)
(3,)
但请注意,如果任何一个可迭代对象都有None
值,这也会将它们过滤掉。如果您不希望这样,请定义您自己的对象fillvalue=
并对其进行过滤,而不是None
:
sentinel = object()
def zip_longest_no_fill(a, b):
for i in itertools.zip_longest(a, b, fillvalue=sentinel):
yield tuple(x for x in i if x is not sentinel)
list(zip_longest_no_fill(a, b)) # [(1, 9), (2, 10), (3,)]
另一种方法是map
:
a = [1, 2, 3]
b = [9, 10]
c = map(None, a, b)
尽管那也将包含(3, None)
而不是(3,)
. 为此,这里有一条有趣的线路:
c = (tuple(y for y in x if y is not None) for x in map(None, a, b))
编写显式 Python 来执行所需的操作并不难:
def izip_short(a, b):
ia = iter(a)
ib = iter(b)
for x in ia:
try:
y = next(ib)
yield (x, y)
except StopIteration:
yield (x,)
break
for x in ia:
yield (x,)
for y in ib:
yield (None, y)
a = [1, 2, 3]
b = [9, 10]
list(izip_short(a, b))
list(izip_short(b, a))
我不确定你想如何处理b
比序列长的a
序列,所以在这种情况下,我只是None
将元组中的第一个值填入 a 中。
为每个序列获取一个显式迭代器。将a
迭代器作为for
循环运行,同时手动使用next(ib)
从b
序列中获取下一个值。如果我们StopIteration
在b
序列上得到 a,我们打破循环,然后for x in ia:
得到a
序列的其余部分;之后for y in ib:
什么都不做,因为那个迭代器已经用完了。或者,如果第一个for x in ia:
循环耗尽了a
迭代器,那么第二个循环for x in ia:
什么也不做,但b
序列中可能会留下一些值,然后for y in ib:
循环收集它们。
单线:
c = zip(a, b) + [(x,) for x in a[len(b):]] + [(x,) for x in b[len(a):]]
如果你想重用这个:
def mergeUsNicely(a, b):
def tupleMe(val):
return (val,)
return zip(a, b) + map(tupleMe, a[len(b):]) + map(tupleMe, b[len(a):])