Data yang berkaitan sering tersimpan dalam list-list terpisah: daftar nama di satu list, daftar skor di list lain, daftar email di list ketiga. Menggabungkannya lewat indeks manual (nama[i], skor[i], satu penghitung dijaga sendiri) berfungsi, tetapi rawan salah dan membosankan. Fungsi bawaan zip() menjalin beberapa iterable berjalan beriringan — seperti kedua sisi resleting yang menyatu satu gigi demi satu gigi.

Memasangkan Elemen dari Beberapa List #

zip() menerima dua iterable atau lebih, lalu menghasilkan aliran tuple yang berisi elemen-elemen pada posisi yang sama:

python
nama = ["Budi", "Siti", "Agus"]
skor = [88, 95, 79]

for n, s in zip(nama, skor):
    print(f"{n}: {s}")

pasangan = list(zip(nama, skor))
print(pasangan)

Output yang Dihasilkan:

text
Budi: 88
Siti: 95
Agus: 79
[('Budi', 88), ('Siti', 95), ('Agus', 79)]

Bedah prosesnya baris per baris:

  1. Baris 4 (zip(nama, skor)): fungsi menyandingkan kedua list dan menghasilkan pasangan (nama, skor) satu per satu — ('Budi', 88) lebih dulu, ('Agus', 79) terakhir.
  2. for n, s in ...: setiap tuple pasangan langsung di-unpack ke dua variabel, seperti enumerate() pada chapter sebelumnya.
  3. Baris 7 (list(zip(...))): zip() sebenarnya menghasilkan iterator lazy; list() memmaterialisasikan seluruh pasangan agar bisa dicetak sekaligus.

zip() juga tidak terbatas pada dua sumber. Tiga list atau lebih berjalan beriringan dengan aturan yang sama, dan setiap elemen hasilnya menjadi tuple sepanjang jumlah sumbernya:

python
nama = ["Budi", "Siti", "Agus"]
skor = [88, 95, 79]
kota = ["Bandung", "Surabaya", "Solo"]

for n, s, k in zip(nama, skor, kota):
    print(f"{n} dari {k}: {s}")

print(list(zip(nama, skor, kota))[0])

Output yang Dihasilkan:

text
Budi dari Bandung: 88
Siti dari Surabaya: 95
Agus dari Solo: 79
('Budi', 88, 'Bandung')

Unpacking di baris for n, s, k in ... kini menangkap tiga nilai per langkah. Baris terakhir menunjukkan bentuk mentahnya: satu elemen zip() adalah tuple ('Budi', 88, 'Bandung') — panjang tuple mengikuti jumlah iterable yang dijalin, dan pengindeksan [0] mengambil elemen pertama aliran tersebut.

Ketika Panjang Tidak Sama #

Jika panjang iterable tidak sama, zip() memotong hasil pada iterable terpendek — sisanya dibuang tanpa peringatan:

python
nama = ["Budi", "Siti", "Agus"]
skor = [88, 95]

print(list(zip(nama, skor)))

Output yang Dihasilkan:

text
[('Budi', 88), ('Siti', 95)]

“Agus” lenyap dari hasil tanpa galat sedikit pun — pemotongan ini disengaja agar zip() aman dipakai pada aliran tak berujung, tetapi bisa menyembunyikan data yang hilang karena salah input.

python
>>> list(zip(["Budi", "Siti", "Agus"], [88, 95], strict=True))
Traceback (most recent call last):
    ...
ValueError: zip() argument 2 is shorter than argument 1

Dengan strict=True, panjang yang tidak cocok berhenti sebagai ValueError yang jelas, bukan data yang hilang diam-diam. Jadikan parameter ini kebiasaan ketika kedua sumber seharusnya berpasangan sempurna.

Membuka Kemasan zip(*…) #

Arah sebaliknya juga sering dibutuhkan: dari daftar pasangan, pisahkan kembali menjadi dua kelompok. Tanda bintang * di depan list memecah elemen list menjadi argumen terpisah — zip(*pasangan) sama dengan zip(("Budi", 88), ("Siti", 95), ("Agus", 79)):

python
pasangan = [("Budi", 88), ("Siti", 95), ("Agus", 79)]

nama, skor = zip(*pasangan)
print(nama)
print(skor)

Output yang Dihasilkan:

text
('Budi', 'Siti', 'Agus')
(88, 95, 79)

Setiap pasangan menjadi satu “baris” argumen; zip() lalu menjalin elemen ke-0 dari semua baris (nama) dan elemen ke-1 dari semua baris (skor). Hasilnya selalu tuple, terlepas dari tipe sumbernya — perlu list? Bungkus dengan list(...).

Membangun Dictionary dari Dua List #

Kombinasi paling produktif dari zip() adalah membangun dictionary: satu list menjadi daftar key, list lain menjadi daftar value:

python
field = ["nama", "email", "kota"]
nilai = ["Budi", "[email protected]", "Bandung"]

pengguna = dict(zip(field, nilai))
print(pengguna)

Output yang Dihasilkan:

text
{'nama': 'Budi', 'email': '[email protected]', 'kota': 'Bandung'}

dict() menerima aliran pasangan dari zip() dan mengubahnya menjadi dictionary utuh dalam satu ekspresi — pola yang jauh lebih ringkas dibanding loop yang menugaskan data[field[i]] = nilai[i] satu per satu. Berbeda dengan dictionary comprehension pada Chapter Dictionary Comprehensions yang menghitung value dari key, pola dict(zip(...)) unggul ketika kedua kolom memang sudah tersedia terpisah.