Existe uma função semelhante a zip que comprime o maior comprimento no Python?

170

Existe uma função interna que funcione como zip()mas que irá preencher os resultados para que o comprimento da lista resultante seja o comprimento da entrada mais longa e não da entrada mais curta ?

>>> 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)]
Mark Harrison
fonte

Respostas:

243

No Python 3 você pode usar itertools.zip_longest

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

Você pode preencher com um valor diferente do que Noneusando o fillvalueparâmetro:

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

Com o Python 2, você pode usar itertools.izip_longest(Python 2.6+) ou mapcom None. É um recursomap pouco conhecido (mas mapalterado no Python 3.x, portanto, isso funciona apenas no Python 2.x).

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
Nadia Alramli
fonte
3
Não temos uma solução Python 3 sem ferramentas?
PascalVKooten
3
@PascalvKooten não é necessário. itertoolsé um módulo C embutido de qualquer maneira.
Antti Haapala 30/08
82

Para o Python 2.6x, use os itertoolsmódulos izip_longest.

Para Python 3, use zip_longest(sem avanço i).

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
SilentGhost
fonte
8
Caso deseje tornar seu código compatível com python 2 e python 3, você pode usá-lo six.moves.zip_longest.
Gamrix
5

solução Python 3 não 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)
dansalmo
fonte
2

Minha solução Python 2:

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

Estou usando uma matriz 2D, mas o conceito é semelhante usando 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]
user12204058
fonte
2
Por favor, adicione uma explicação sobre por que esse código funciona. Ou porque é a resposta certa
Suit Boy Aplicativos