【问题标题】:Is there a zip-like function that pads to longest length?是否有类似拉链的功能可以填充到最长的长度?
【发布时间】:2010-11-19 14:55:26
【问题描述】:

是否有一个像zip() 一样工作的内置函数,但它会填充结果,以便结果列表的长度是 longest 输入的长度而不是 最短的输入?

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

【问题讨论】:

    标签: python list zip


    【解决方案1】:

    在 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+),也可以将 mapNone 一起使用。 feature of map 鲜为人知(但 map 在 Python 3.x 中发生了变化,因此这只适用于 Python 2.x)。

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

    【讨论】:

    • 我们没有非 itertools Python 3 解决方案吗?
    • @PascalvKooten 这不是必需的。 itertools 无论如何都是内置的 C 模块。
    【解决方案2】:

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

    【讨论】:

    • 如果你想让你的代码同时兼容python 2和python 3,你可以使用six.moves.zip_longest来代替。
    【解决方案3】:

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

    【讨论】:

    • 这适用于 micropython,谢谢@dansalmo!
    【解决方案4】:

    非 itertools 我的 Python 2 解决方案:

    if len(list1) < len(list2):
        list1.extend([None] * (len(list2) - len(list1)))
    else:
        list2.extend([None] * (len(list1) - len(list2)))
    

    【讨论】:

      【解决方案5】:

      除了接受的答案之外,如果您正在使用 可能不应该长度不同的迭代,建议将 strict=True 传递给zip()(从 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 参数,任何错误 导致不同长度的迭代将被静音, 可能表现为在另一部分中难以发现的错误 程序。

      【讨论】:

        【解决方案6】:

        我使用的是二维数组,但概念与使用 python 2.x 类似:

        if len(set([len(p) for p in printer])) > 1:
            printer = [column+['']*(max([len(p) for p in printer])-len(column)) for column in printer]
        

        【讨论】:

        • 请解释为什么这段代码有效。或者为什么它是正确的答案
        猜你喜欢
        • 2011-02-10
        • 2011-10-05
        • 2016-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-15
        • 2020-09-30
        相关资源
        最近更新 更多