有没有类似拉链的功能可以填充到最长的长度?

发布于 2024-07-30 17:18:36 字数 447 浏览 4 评论 0原文

是否有一个内置函数,其工作方式类似于 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)]

Is there a built-in function that works like zip() but that will pad the results so that the length of the resultant list is the length of the longest input rather than the shortest input?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

甜尕妞 2024-08-06 17:18:37

要添加到已经给出的答案中,以下内容适用于任何可迭代对象,并且不使用itertools,回答@ProdIssue的问题:

def zip_longest(*iterables, default_value):
    iterators = tuple(iter(i) for i in iterables)
    sentinel = object()
    while True:
        new = tuple(next(i, sentinel) for i in iterators)
        if all(n is sentinel for n in new):
            return
        yield tuple(default_value if n is sentinel else n for n in new)

需要使用sentinel,因此迭代器会产生< code>default_value 不会被错误地识别为空。

To add to the answers already given, the following works for any iterable and does not use itertools, answering @ProdIssue's question:

def zip_longest(*iterables, default_value):
    iterators = tuple(iter(i) for i in iterables)
    sentinel = object()
    while True:
        new = tuple(next(i, sentinel) for i in iterators)
        if all(n is sentinel for n in new):
            return
        yield tuple(default_value if n is sentinel else n for n in new)

The use of sentinel is needed so an iterator yielding default_value will not be erroneously be identified as empty.

荒路情人 2024-08-06 17:18:37

只需使用迭代器,没什么花哨的。

def zip_longest(*iterables):
    items = 0
    for iterable in iterables:
        items = max(items, len(iterable))

    iters = [iter(iterable) for iterable in iterables]
    while items:
        yield (*[next(i, None) for i in iters],)
        items -= 1

Just use iterators, nothing fancy.

def zip_longest(*iterables):
    items = 0
    for iterable in iterables:
        items = max(items, len(iterable))

    iters = [iter(iterable) for iterable in iterables]
    while items:
        yield (*[next(i, None) for i in iters],)
        items -= 1
月下凄凉 2024-08-06 17:18:37

我使用的是二维数组,但概念与使用 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]

Im using a 2d array but the concept is the similar using 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]
当爱已成负担 2024-08-06 17:18:36

在Python 3中,您可以使用 itertools.zip_longest< /a>

>>> 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。 这是一个鲜为人知的 map 功能(但是 map 在 Python 3.x 中发生了变化,因此这只适用于 Python 2.x)。

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

In Python 3 you can use itertools.zip_longest

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

You can pad with a different value than None by using the fillvalue parameter:

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

With Python 2 you can either use itertools.izip_longest (Python 2.6+), or you can use map with None. It is a little known feature of map (but map changed in Python 3.x, so this only works in Python 2.x).

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
怼怹恏 2024-08-06 17:18:36

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

For Python 2.6x use itertools module's izip_longest.

For Python 3 use zip_longest instead (no leading i).

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
七色彩虹 2024-08-06 17:18:36

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

引用文档:

zip() 通常用于假定可迭代对象为
长度相等。 在这种情况下,建议使用 strict=True
选项。 它的输出与常规 zip() 相同:

<前><代码>>>> 列表(zip(('a', 'b', 'c'), (1, 2, 3), strict=True))
[('a', 1), ('b', 2), ('c', 3)]

与默认行为不同,它检查
可迭代对象的长度是相同的,如果它们相同,则会引发 ValueError
不是:

<前><代码>>>> 列表(zip(范围(3),['费用','fi','fo','fum'],严格= True))
回溯(最近一次调用最后一次):
...
ValueError: zip() 参数 2 比参数 1 长

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

In addition to the accepted answer, if you're working with iterables that might be different lengths but shouldn't be, it's recommended to pass strict=True to zip() (supported since Python 3.10).

To quote the documentation:

zip() is often used in cases where the iterables are assumed to be of
equal length. In such cases, it’s recommended to use the strict=True
option. Its output is the same as regular zip():

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

Unlike the default behavior, it checks that the
lengths of iterables are identical, raising a ValueError if they
aren’t:

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

Without the strict=True argument, any bug
that results in iterables of different lengths will be silenced,
possibly manifesting as a hard-to-find bug in another part of the
program.

东京女 2024-08-06 17:18:36

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

non itertools Python 3 solution:

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)
梦毁影碎の 2024-08-06 17:18:36

非 itertools 我的 Python 2 解决方案:

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

non itertools My Python 2 solution:

if len(list1) < len(list2):
    list1.extend([None] * (len(list2) - len(list1)))
else:
    list2.extend([None] * (len(list1) - len(list2)))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文