Czy w Pythonie istnieje funkcja podobna do zip, która dopełnia najdłuższą długość?

170

Czy istnieje funkcja wbudowana, która działa podobnie, zip()ale będzie wypełniać wyniki tak, że długość wynikowej listy będzie długością najdłuższego wejścia, a nie najkrótszego wejścia?

>>> 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
źródło

Odpowiedzi:

243

W Pythonie 3 możesz użyć itertools.zip_longest

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

Możesz dopełnić inną wartością niż Noneza pomocą fillvalueparametru:

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

W Pythonie 2 możesz użyć itertools.izip_longest(Python 2.6+) lub możesz użyć mapz None. To mało znane funkcjamap (ale mapzmieniona w Pythonie 3.x, więc działa tylko w Pythonie 2.x).

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
Nadia Alramli
źródło
3
Czy nie mamy rozwiązania innego niż itertools w Pythonie 3?
PascalVKooten
3
@PascalvKooten nie jest wymagane. itertoolsi tak jest wbudowanym modułem C.
Antti Haapala
82

W przypadku Pythona 2.6x użyj itertoolsmodułów izip_longest.

W przypadku Pythona 3 użyj zip_longestzamiast tego (bez wiodących i).

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
SilentGhost
źródło
8
Jeśli chcesz, aby Twój kod był zgodny zarówno z Pythonem 2, jak i Pythonem 3, możesz użyć six.moves.zip_longestzamiast tego.
Gamrix,
5

Rozwiązanie non itertools w Pythonie 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)
dansalmo
źródło
2

non itertools Moje rozwiązanie dla Pythona 2:

if len(list1) < len(list2):
    list1.extend([None] * (len(list2) - len(list1)))
else:
    list2.extend([None] * (len(list1) - len(list2)))
Helton Wernik
źródło
0

Używam tablicy 2d, ale koncepcja jest podobna w przypadku Pythona 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
źródło
2
Dodaj wyjaśnienie, dlaczego ten kod działa. Albo dlaczego jest to właściwa odpowiedź
Suit Boy Apps