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

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

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

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)

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

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]

2
Dodaj wyjaśnienie, dlaczego ten kod działa. Albo dlaczego jest to właściwa odpowiedź
Suit Boy Apps
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.