Вопрос-Ответ

Is there a zip-like function that pads to longest length?

Существует ли zip-подобная функция, которая дополняет до наибольшей длины?

Есть ли встроенная функция, которая работает как 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)]
Переведено автоматически
Ответ 1

В Python 3 вы можете использовать itertools.zip_longest

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

Вы можете дополнить файл значением, отличным от None с помощью fillvalue параметра:

>>> 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)]
Ответ 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)]
Ответ 3

В дополнение к принятому ответу, если вы работаете с итерациями, которые могут иметь разную длину, но не должны быть такими, рекомендуется передать 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 аргументов, либо ошибка
что приводит к итерируемые объекты разной длины будут молчать,
возможно, проявляющейся как трудно найти ошибку в другой части
программы.


Ответ 4

решение на Python 3, отличное от itertools:

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)
python list