Python:类似拉链的功能,填充到最长的长度?

Mar*_*son 146 python zip list

是否有一个内置函数,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)]
Run Code Online (Sandbox Code Playgroud)

Nad*_*mli 207

在Python 3中,您可以使用 itertools.zip_longest

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

您可以使用与None使用fillvalue参数不同的值填充:

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

使用Python 2,你既可以使用itertools.izip_longest(Python的2.6+),也可以使用mapNone.它是一个鲜为人知的特性map(但map在Python 3.x中有所改变,所以这只适用于Python 2.x).

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
Run Code Online (Sandbox Code Playgroud)

  • 我们没有非itertools Python 3解决方案吗? (3认同)
  • @PascalvKooten不需要。无论如何,`itertools`是一个内置的C模块。 (3认同)

Sil*_*ost 79

对于Python 2.6x使用itertools模块izip_longest.

对于Python 3使用zip_longest(没有领先i).

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
Run Code Online (Sandbox Code Playgroud)

  • 如果你想使你的代码兼容python 2和python 3,你可以使用`six.moves.zip_longest`代替. (8认同)

Eug*_*ash 15

除了已接受的答案之外,如果您正在使用可能具有不同长度但不应该是不同长度的迭代,建议传递strict=Truezip()(自 Python 3.10 起支持)。

\n

引用文档:

\n
\n

zip()通常在假定迭代器长度相等的情况下使用。在这种情况下,\xe2\x80\x99s 建议使用strict=True\n选项。它的输出与常规的相同zip()

\n
>>> list(zip((\'a\', \'b\', \'c\'), (1, 2, 3), strict=True))\n[(\'a\', 1), (\'b\', 2), (\'c\', 3)]\n
Run Code Online (Sandbox Code Playgroud)\n

与默认行为不同,它检查\n可迭代的长度是否相同,ValueError如果\n\n\xe2\x80\x99t 则引发 a:

\n
>>> list(zip(range(3), [\'fee\', \'fi\', \'fo\', \'fum\'], strict=True))\nTraceback (most recent call last):\n...\nValueError: zip() argument 2 is longer than argument 1\n
Run Code Online (Sandbox Code Playgroud)\n

如果没有strict=True参数,任何导致不同长度的可迭代的错误都将被静音,可能在程序的其他部分表现为难以发现的错误。

\n
\n


dan*_*lmo 9

非 itertools Python 3 解决方案:

def zip_longest(*lists):
    def g(l):
        for item in l:
            yield item
        while True:
            yield None
    gens = [g(l) for l in lists]    
    for _ in range(max(map(len, lists))):
        yield tuple(next(g) for g in gens)
Run Code Online (Sandbox Code Playgroud)