Gibt es eine zip-ähnliche Funktion, die in Python auf die längste Länge aufgefüllt wird?


170

Gibt es eine integrierte Funktion, die wie zip()folgt funktioniert, aber die Ergebnisse auffüllt, sodass die Länge der resultierenden Liste eher der Länge der längsten Eingabe als der kürzesten Eingabe entspricht?

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

Antworten:


243

In Python 3 können Sie verwenden itertools.zip_longest

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

Sie können mit einem anderen Wert als Nonemit dem folgenden fillvalueParameter auffüllen:

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

Mit Python 2 können Sie entweder itertools.izip_longest(Python 2.6+) oder mapmit verwenden None. Es ist eine wenig bekannte Funktion vonmap (wurde jedoch mapin Python 3.x geändert, sodass dies nur in Python 2.x funktioniert).

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

3
Haben wir keine Python 3-Lösung ohne itertools?
PascalVKooten

3
@PascalvKooten ist nicht erforderlich. itertoolsist sowieso ein eingebautes C-Modul.
Antti Haapala

82

Verwenden Sie für Python 2.6x itertoolsModule izip_longest.

Verwenden Sie zip_longeststattdessen Python 3 (kein führendes i).

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

8
Wenn Sie Ihren Code sowohl für Python 2 als auch für Python 3 kompatibel machen möchten, können Sie ihn six.moves.zip_longeststattdessen verwenden.
Gamrix

5

Nicht-Itertools Python 3-Lösung:

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 Meine Python 2-Lösung:

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

0

Ich benutze ein 2d Array, aber das Konzept ist das gleiche mit 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
Bitte fügen Sie eine Erklärung hinzu, warum dieser Code funktioniert. Oder warum es die richtige Antwort ist
Suit Boy Apps
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.