是否有类似zip的函数可以填充到最长长度?

276 投票
8 回答
133059 浏览
提问于 2025-04-15 13:36

有没有一个内置的函数,它的功能和 zip() 类似,但它会填充结果,使得最终得到的列表长度是所有输入中最长的那个,而不是最短的?

>>> a = ['a1']
>>> b = ['b1', 'b2', 'b3']
>>> c = ['c1', 'c2']

>>> zip(a, b, c)
[('a1', 'b1', 'c1')]

>>> What command goes here?
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

8 个回答

15

除了已经接受的答案,如果你在处理一些可能长度不同但实际上应该相同的可迭代对象,建议在使用zip()时加上strict=True这个参数(从Python 3.10开始支持)。

引用一下文档内容:

zip()通常用于假设可迭代对象长度相等的情况。在这种情况下,建议使用strict=True选项。它的输出和普通的zip()是一样的:

>>> list(zip(('a', 'b', 'c'), (1, 2, 3), strict=True))
[('a', 1), ('b', 2), ('c', 3)]

但是,与默认行为不同的是,它会检查可迭代对象的长度是否一致,如果不一致就会抛出一个ValueError错误:

>>> list(zip(range(3), ['fee', 'fi', 'fo', 'fum'], strict=True))
Traceback (most recent call last):
...
ValueError: zip() argument 2 is longer than argument 1

如果没有strict=True这个参数,任何导致可迭代对象长度不同的错误都会被忽略,可能会在程序的其他部分表现为一个难以发现的bug。

92

对于Python 2.6版本,可以使用itertools模块里的izip_longest

而如果你使用的是Python 3,就用zip_longest,注意这里没有前面的i

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
389

在Python 3中,你可以使用itertools.zip_longest这个功能。

>>> list(itertools.zip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

你可以通过使用fillvalue这个参数,来填充一个不同于None的值。

>>> list(itertools.zip_longest(a, b, c, fillvalue='foo'))
[('a1', 'b1', 'c1'), ('foo', 'b2', 'c2'), ('foo', 'b3', 'foo')]

在Python 2中,你可以使用itertools.izip_longest(需要Python 2.6及以上版本),或者你也可以用map配合None。这是map的一个不太为人知的特性(不过map在Python 3.x中有变化,所以这个方法只适用于Python 2.x)。

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

撰写回答