Apakah ada fungsi mirip zip yang panjangnya terpanjang dengan Python?

170

Apakah ada fungsi built-in yang berfungsi seperti zip()tetapi yang akan memberi pad hasil sehingga panjang daftar yang dihasilkan adalah panjang dari input terpanjang daripada input terpendek ?

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

Jawaban:

243

Di Python 3 Anda bisa menggunakan itertools.zip_longest

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

Anda dapat membuat pad dengan nilai yang berbeda daripada Nonedengan menggunakan fillvalueparameter:

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

Dengan Python 2 Anda bisa menggunakan itertools.izip_longest(Python 2.6+), atau Anda dapat menggunakan mapdengan None. Ini adalah sedikit diketahui fiturmap (tapi mapberubah dengan Python 3.x, jadi ini hanya bekerja dengan Python 2.x).

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
Nadia Alramli
sumber
3
Apakah kita tidak memiliki solusi Python 3 non itertools?
PascalVKooten
3
@PascalvKooten tidak diperlukan. itertoolsadalah modul builtin C pula.
Antti Haapala
82

Untuk Python 2.6x gunakan itertoolsmodul izip_longest.

Untuk Python 3 gunakan zip_longestsebagai gantinya (tidak ada yang memimpin i).

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]
SilentGhost
sumber
8
Jika Anda ingin membuat kode Anda berdua python 2 dan python 3 kompatibel, Anda bisa menggunakannya six.moves.zip_longest.
Gamrix
5

solusi non 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)
dansalmo
sumber
2

solusi non itertools My Python 2:

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

Saya menggunakan array 2d tetapi konsepnya mirip dengan menggunakan 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]
pengguna12204058
sumber
2
Harap tambahkan penjelasan mengapa kode ini berfungsi. Atau mengapa itu adalah jawaban yang tepat
Aplikasi Suit Boy