¿Existe una función de tipo zip que se adapta a la longitud más larga en Python?


170

¿Existe una función incorporada que funcione zip()pero que rellene los resultados para que la longitud de la lista resultante sea la longitud de la entrada más larga en lugar de la más corta ?

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

Respuestas:


243

En Python 3 puedes usar itertools.zip_longest

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

Puede rellenar con un valor diferente Noneal usar el fillvalueparámetro:

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

Con Python 2 puede usar itertools.izip_longest(Python 2.6+), o puede usar mapcon None. Es una característicamap poco conocida de (pero mapcambió en Python 3.x, por lo que solo funciona en Python 2.x).

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

3
¿No tenemos una solución Python 3 que no sea itertools?
PascalVKooten

3
@PascalvKooten no es obligatorio. itertoolses un módulo C incorporado de todos modos.
Antti Haapala

82

Para Python 2.6x, use los itertoolsmódulos izip_longest.

Para Python 3, use zip_longesten su lugar (sin encabezado i).

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

8
En caso de que desee que su código sea compatible tanto con python 2 como con python 3, puede usarlo six.moves.zip_longest.
Gamrix

5

Solución no 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)

2

Solución no itertools My Python 2:

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

0

Estoy usando una matriz 2d pero el concepto es similar al uso de 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]

2
Agregue una explicación de por qué funciona este código. O por qué es la respuesta correcta
Suit Boy Apps
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.