Esiste una funzione simile a una zip che si adatta alla lunghezza più lunga in Python?


170

Esiste una funzione integrata che funziona come, zip()ma che riempie i risultati in modo che la lunghezza dell'elenco risultante sia la lunghezza dell'input più lungo anziché quello più breve ?

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

Risposte:


243

In Python 3 puoi usare itertools.zip_longest

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

Puoi pad con un valore diverso rispetto Nonea usando il fillvalueparametro:

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

Con Python 2 puoi usare itertools.izip_longest(Python 2.6+), oppure puoi usare mapcon None. È una caratteristica poco nota dimap (ma mapmodificata in Python 3.x, quindi funziona solo in Python 2.x).

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

3
Non abbiamo una soluzione Python 3 non itertools?
PascalVKooten,

3
@PascalvKooten non è richiesto. itertoolsè comunque un modulo C incorporato.
Antti Haapala,

82

Per Python 2.6x usa il itertoolsmodulo izip_longest.

Per Python 3 usare zip_longestinvece (nessun vantaggio i).

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

8
Nel caso in cui desideri rendere compatibile il tuo codice sia python 2 che python 3, puoi six.moves.zip_longestinvece usarlo .
Gamrix,

5

soluzione Python 3 non 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)

2

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

0

Sto usando un array 2d ma il concetto è simile 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]

2
Aggiungi una spiegazione sul perché questo codice funziona. O perché è la risposta giusta
Suit Boy Apps,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.