BAB 15: Slicing dan List Comprehension
Potong list dengan presisi menggunakan slicing, lalu bangun list baru secara ringkas dengan list comprehension — dua teknik yang mengubah cara kamu bekerja dengan data kolektif.
Di bab sebelumnya, ekspresi baris[1:] muncul begitu saja saat kita mengambil semua skor dari nested list — tanpa penjelasan mendalam tentang mekanismenya. Notasi [1:] itu adalah slicing: cara Python memotong sebagian list menjadi list baru. Dan setelah kamu menguasai slicing, ada satu lagi teknik yang akan mengubah cara kamu membuat list: list comprehension. Keduanya adalah alat yang membuat kode Python terasa ringkas tanpa mengorbankan kejelasan.
Slicing — Memotong List
Slicing menggunakan notasi [start:stop:step] di dalam kurung siku. Hasilnya selalu list baru — list asli tidak tersentuh.
# kuis.py — ekstrak sebagian peserta
peserta = ["Rina", "Budi", "Sari", "Dimas", "Lina"]
# ambil elemen dari index 1 sampai sebelum index 3
tengah = peserta[1:3]
print(tengah)
['Budi', 'Sari']
Tiga komponen slicing bekerja seperti ini:
| Komponen | Arti | Default |
|---|---|---|
start | Index awal (termasuk) | 0 |
stop | Index akhir (tidak termasuk) | len(list) |
step | Langkah / jarak antar elemen | 1 |
Ketiga komponen ini opsional. Jika dikosongkan, Python menggunakan nilai default.
Visualisasi Index dan Slicing
Cara termudah memahami slicing adalah membayangkan index sebagai garis pemisah antar elemen, bukan posisi elemen itu sendiri.
Saat kamu menulis peserta[1:3], Python memotong di garis pemisah index 1 dan index 3 — menghasilkan semua elemen di antara kedua garis itu: ["Budi", "Sari"].
Dengan cara pandang ini, beberapa pola slicing yang tadinya membingungkan jadi masuk akal:
peserta[:3] --> potong dari awal sampai garis 3 --> ["Rina", "Budi", "Sari"]
peserta[3:] --> potong dari garis 3 sampai akhir --> ["Dimas", "Lina"]
peserta[:-1] --> potong dari awal sampai garis -1 --> ["Rina", "Budi", "Sari", "Dimas"]
peserta[1:-1] --> potong dari garis 1 sampai -1 --> ["Budi", "Sari", "Dimas"]
Ilustrasi ini juga menjelaskan mengapa peserta[2:2] menghasilkan list kosong [] — garis start dan stop berada di posisi yang sama, jadi tidak ada elemen di antaranya.
Slicing dengan start dan stop
# kuis.py
skor = [85, 76, 91, 68, 77, 82, 95]
tiga_pertama = skor[:3] # dari awal sampai index 2
tiga_terakhir = skor[-3:] # 3 elemen terakhir
tanpa_ujung = skor[1:-1] # tanpa elemen pertama dan terakhir
print(f"Tiga pertama: {tiga_pertama}")
print(f"Tiga terakhir: {tiga_terakhir}")
print(f"Tanpa ujung: {tanpa_ujung}")
Tiga pertama: [85, 76, 91]
Tiga terakhir: [82, 95, 77]
Tanpa ujung: [76, 91, 68, 77, 82]
Pola [:n] untuk n elemen pertama dan [-n:] untuk n elemen terakhir adalah dua pola yang akan sangat sering kamu gunakan.
Slicing dengan step
Parameter ketiga menentukan langkah. Nilai 2 berarti ambil setiap elemen kedua, 3 setiap elemen ketiga, dan seterusnya.
# kuis.py — ambil elemen di posisi genap dan ganjil
skor = [85, 76, 91, 68, 77, 82, 95]
genap = skor[::2] # index 0, 2, 4, 6
ganjil = skor[1::2] # index 1, 3, 5
print(f"Index genap: {genap}")
print(f"Index ganjil: {ganjil}")
Index genap: [85, 91, 77, 95]
Index ganjil: [76, 68, 82]
Step negatif membalik arah traversal. Pola [::-1] adalah cara paling ringkas untuk membalik seluruh list:
# kuis.py
peserta = ["Rina", "Budi", "Sari", "Dimas", "Lina"]
terbalik = peserta[::-1]
print(terbalik)
['Lina', 'Dimas', 'Sari', 'Budi', 'Rina']
Berbeda dengan reverse() yang mengubah list asli, [::-1] menghasilkan list baru — list peserta tetap dalam urutan semula.
Visualisasi step membantu melihat elemen mana yang “dilompati”:
skor = [85, 76, 91, 68, 77, 82, 95]
Index: 0 1 2 3 4 5 6
skor[::2] --> ambil setiap 2 langkah dari awal
* * * *
85 91 77 95
skor[1::2] --> mulai dari index 1, lalu setiap 2 langkah
* * *
76 68 82
skor[::-1] --> mundur dari akhir ke awal
95 82 77 68 91 76 85
Slicing untuk Mengubah List
Slicing bukan hanya untuk membaca. Kamu juga bisa mengganti sebagian elemen sekaligus menggunakan assignment ke slice:
# kuis.py — ganti tiga skor tengah sekaligus
skor = [85, 76, 91, 68, 77]
skor[1:4] = [80, 93, 70]
print(skor)
[85, 80, 93, 70, 77]
Panjang list pengganti tidak harus sama dengan panjang slice yang diganti. Python akan menyesuaikan — bisa memperpanjang atau memperpendek list. Pastikan ini memang yang kamu inginkan sebelum menggunakan fitur ini.
List Comprehension — Membuat List Ringkas
Sejauh ini, setiap kali kita perlu membangun list baru dari data yang sudah ada, polanya selalu sama: buat list kosong, loop, lalu append().
# kuis.py — cara konvensional: ambil skor yang lulus
skor = [85, 72, 91, 68, 77, 45, 93, 58]
BATAS_LULUS = 70
lulus = []
for s in skor:
if s >= BATAS_LULUS:
lulus.append(s)
print(lulus)
[85, 72, 91, 77, 93]
Tiga baris (inisialisasi, loop, append) untuk operasi yang sebenarnya sederhana. List comprehension meringkas pola ini menjadi satu baris:
# kuis.py — list comprehension
skor = [85, 72, 91, 68, 77, 45, 93, 58]
BATAS_LULUS = 70
lulus = [s for s in skor if s >= BATAS_LULUS]
print(lulus)
[85, 72, 91, 77, 93]
Hasilnya identik, tapi ekspresinya lebih deklaratif: “ambil setiap s dari skor jika s >= batas lulus”. Formatnya mengikuti pola [ekspresi for variabel in iterable if kondisi].
Transformasi Elemen
List comprehension bukan hanya filter — bagian ekspresi di depan bisa melakukan transformasi apapun terhadap setiap elemen.
# kuis.py — konversi skor ke persentase (skor maksimal 100)
skor = [85, 72, 91, 68, 77]
persentase = [f"{s}%" for s in skor]
print(persentase)
['85%', '72%', '91%', '68%', '77%']
Contoh lain — menghitung bonus poin berdasarkan skor:
# kuis.py — bonus 5 poin untuk skor di bawah 75
skor = [85, 72, 91, 68, 77]
skor_final = [s + 5 if s < 75 else s for s in skor]
print(skor_final)
[85, 77, 91, 73, 77]
Perhatikan posisi if...else di sini: ketika digunakan sebagai ekspresi ternary (bagian dari transformasi), ia ditulis sebelum for. Ini berbeda dari if sebagai filter yang ditulis setelah for. Perbedaan posisi ini penting:
[ekspresi if kondisi else alternatif for x in data]— transformasi kondisional, semua elemen tetap masuk[ekspresi for x in data if kondisi]— filter, hanya elemen yang lolos kondisi yang masuk
Comprehension dari range()
Ingat range() dari BAB 11? Ia menjadi pasangan natural list comprehension untuk membuat list angka dengan pola tertentu.
# kuis.py — buat nomor soal
nomor_soal = [f"Soal {i}" for i in range(1, 11)]
print(nomor_soal)
['Soal 1', 'Soal 2', 'Soal 3', 'Soal 4', 'Soal 5', 'Soal 6', 'Soal 7', 'Soal 8', 'Soal 9', 'Soal 10']
# kuadrat dari angka 1 sampai 5
kuadrat = [n ** 2 for n in range(1, 6)]
print(kuadrat)
[1, 4, 9, 16, 25]
Bandingkan dengan cara manual: tanpa comprehension, kamu perlu empat baris (list kosong, for, append, selesai). Dengan comprehension, cukup satu baris yang langsung menjelaskan apa yang dihasilkan.
Nested Comprehension
List comprehension bisa memuat loop bersarang — berguna untuk menghasilkan kombinasi atau memproses data dua dimensi.
# kuis.py — semua kombinasi sesi dan ruangan
sesi = ["Pagi", "Siang"]
ruangan = ["A", "B", "C"]
jadwal = [f"{s} - Ruang {r}" for s in sesi for r in ruangan]
for j in jadwal:
print(j)
Pagi - Ruang A
Pagi - Ruang B
Pagi - Ruang C
Siang - Ruang A
Siang - Ruang B
Siang - Ruang C
Urutan for di comprehension sama dengan urutan loop bersarang biasa: loop luar ditulis lebih dulu, loop dalam setelahnya.
Comprehension juga bisa menghasilkan nested list — misalnya membuat matriks skor:
# kuis.py — buat template skor kosong untuk 4 peserta, 3 soal
template_skor = [[0 for soal in range(3)] for peserta in range(4)]
for baris in template_skor:
print(baris)
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]
Pada contoh di atas, comprehension dalam ([0 for soal in range(3)]) membuat satu baris berisi tiga nol, dan comprehension luar mengulanginya empat kali untuk membuat empat baris.
List comprehension memang ringkas, tapi jangan terlalu memaksakannya. Jika ekspresi comprehension sudah melebihi satu baris atau memerlukan lebih dari satu for dengan if, seringkali loop biasa justru lebih mudah dibaca dan di-debug. Prioritaskan kejelasan di atas keringkasan.
Fungsi slice()
Selama ini kita menulis slicing langsung di kurung siku: skor[1:4], peserta[:3]. Tapi bagaimana kalau kamu ingin menyimpan instruksi slice itu sendiri ke dalam variabel dan menggunakannya berulang kali? Python menyediakan fungsi bawaan slice() untuk keperluan ini.
# kuis.py — slice sebagai objek
skor = [85, 76, 91, 68, 77, 82, 95]
# definisikan pola slice sekali
tiga_pertama = slice(0, 3)
tiga_terakhir = slice(-3, None)
# gunakan berkali-kali
print(skor[tiga_pertama])
print(skor[tiga_terakhir])
[85, 76, 91]
[82, 95, 77]
slice(start, stop, step) menerima parameter yang sama dengan notasi [start:stop:step]. Nilai None digunakan untuk parameter yang ingin dibiarkan default — slice(None, 3) setara dengan [:3], dan slice(None, None, -1) setara dengan [::-1].
Objek slice berguna saat pola pemotongan yang sama perlu diterapkan ke beberapa list berbeda:
# kuis.py — satu slice untuk banyak list
ambil_tengah = slice(1, -1)
peserta = ["Rina", "Budi", "Sari", "Dimas", "Lina"]
skor_sesi1 = [85, 76, 91, 68, 77]
skor_sesi2 = [79, 82, 88, 71, 90]
print(peserta[ambil_tengah])
print(skor_sesi1[ambil_tengah])
print(skor_sesi2[ambil_tengah])
['Budi', 'Sari', 'Dimas']
[76, 91, 68]
[82, 88, 71]
Dalam kode sehari-hari, notasi [start:stop:step] langsung di kurung siku sudah cukup. Fungsi slice() lebih relevan saat kamu membangun pola slice secara dinamis — misalnya dari konfigurasi atau input user.
Slicing + Comprehension
Kedua teknik ini sering bekerja bersama. Ingat nested list hasil_kuis dari BAB 14? Kita bisa menggabungkan slicing dan comprehension untuk mengekstrak data dengan sangat ringkas.
# kuis.py — dari BAB 14
hasil_kuis = [
["Rina", 85, 90, 78],
["Budi", 76, 68, 82],
["Sari", 91, 95, 88],
["Dimas", 68, 72, 65],
]
# ambil nama peserta yang rata-ratanya di atas 80
unggul = [
baris[0]
for baris in hasil_kuis
if sum(baris[1:]) / len(baris[1:]) > 80
]
print(f"Peserta unggul: {unggul}")
Peserta unggul: ['Rina', 'Sari']
Di sini baris[1:] (slicing) mengambil semua skor tanpa nama, lalu comprehension mem-filter peserta berdasarkan rata-ratanya. Kode yang dulunya butuh loop, variabel penampung, dan kondisi bertingkat, sekarang cukup satu ekspresi yang bisa dibaca hampir seperti kalimat: “ambil nama dari setiap baris di hasil kuis jika rata-rata skornya di atas 80”.
Latihan
Tiga tantangan ini mengombinasikan slicing dan list comprehension dengan konsep dari bab-bab sebelumnya:
-
Kamu punya list
skor = [85, 72, 91, 68, 77, 45, 93, 58, 82, 67]. Gunakan slicing untuk mengambil 5 elemen pertama dan 5 elemen terakhir ke dalam dua list terpisah. Lalu, gunakan list comprehension untuk membuat list baru yang hanya berisi skor di atas rata-rata keseluruhan (gunakansum()danlen()untuk menghitung rata-rata). -
Buat list
hurufdari string “KUISPYTHON” menggunakanlist(). Gunakan slicing dengan step untuk mengambil huruf di posisi genap saja, lalu balik hasilnya dengan[::-1]. Cetak hasil akhirnya. -
Kamu punya nested list hasil kuis dari 5 peserta dengan masing-masing 4 skor soal. Gunakan list comprehension untuk membuat list baru berisi tuple
(nama, rata_rata)untuk setiap peserta. Kemudian, gunakan list comprehension lagi untuk memfilter hanya peserta dengan rata-rata di atas 75 dan cetak hasilnya.
Slicing dan list comprehension membuat kode Python terasa ekspresif — kamu mendeskripsikan apa yang diinginkan, bukan bagaimana langkah demi langkahnya. Sejauh ini semua tipe data kolektif yang kita gunakan bisa diubah isinya kapan saja. Tapi bagaimana jika kamu butuh kumpulan data yang dijamin tidak berubah setelah dibuat? Python punya tipe khusus untuk itu — dan itulah yang akan kita eksplorasi selanjutnya.