Mengubah setiap harga menjadi harga bertype pajak, menyaring produk mahal, menjumlahkan subtotal — pekerjaan mengolah koleksi seperti ini muncul di hampir semua program. Cara manual dengan loop for dan append selalu berhasil, tetapi tiga tool bawaan Python menyediakan bentuk yang lebih deklaratif: map untuk mentransformasi, filter untuk menyaring, dan reduce untuk meringkas. Memahami ketiganya juga membantu membaca kode library modern yang memakai gaya fungsional.
map: Satu Function, Banyak Elemen #
map(function, iterable) menerapkan satu function ke setiap elemen. Kuncinya: map tidak langsung membangun list — map mengembalikan object lazy iterator yang baru menghitung saat elemennya diminta:
kuadrat = map(lambda x: x ** 2, [1, 2, 3, 4])
print(type(kuadrat).__name__)
print(next(kuadrat))
print(list(kuadrat))Output yang Dihasilkan:
map
1
[4, 9, 16]Mari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 1 (
kuadrat = map(...)): pemanggilanmapbelum menyentuh satu elemen pun — yang dibuat hanyalah objectmapyang menyimpan rencana transformasi. - Baris 2 (
print(type(...))): tipe hasilnya adalahmap, bukanlist. - Baris 4 (
next(kuadrat)):nextmemaksa elemen pertama dihitung —1 ** 2menghasilkan1. Elemen tersebut kini habis dikonsumsi. - Baris 5 (
list(kuadrat)):listmemaksa sisa elemen — hasilnya[4, 9, 16], hanya tiga nilai, karena elemen pertama sudah terpakai.
Perilaku lazy ini sama dengan generator yang kita pelajari pada Chapter Generator Expressions dan Lazy Evaluation: hemat memori untuk data besar, tetapi iterator hanya bisa dikonsumsi sekali.
map juga menerima lebih dari satu iterable. Function diterapkan paralel per posisi, dan pemrosesan berhenti di iterable terpendek:
harga = [15000, 22500, 8000]
jumlah = [2, 1, 3]
subtotal = list(map(lambda h, j: h * j, harga, jumlah))
print(subtotal)Output yang Dihasilkan:
[30000, 22500, 24000]Lambda (h, j) menerima satu harga dan satu jumlah pada posisi yang sama, lalu mengalikannya — pola yang sejalan dengan perilaku zip pada Chapter zip().
filter: Menyaring Elemen #
filter(function, iterable) hanya meloloskan elemen yang membuat function mengembalikan nilai truthy:
produk = [("kopi", 45000), ("gula", 12000), ("teh", 25000), ("susu", 32000)]
murah = list(filter(lambda p: p[1] < 30000, produk))
print(murah)Output yang Dihasilkan:
[('gula', 12000), ('teh', 25000)]Lambda membaca harga di p[1]; hanya produk di bawah 30000 lolos. Sama seperti map, hasil filter adalah iterator lazy yang perlu dimaterialisasi dengan list.
reduce: Meringkas Banyak menjadi Satu #
map dan filter menjaga jumlah elemen. reduce mengecilkannya menjadi satu nilai dengan menggulung elemen satu per satu ke sebuah accumulator. Di Python 2 reduce adalah built-in; di Python 3 function ini pindah ke module functools — keputusan yang mencerminkan bahwa loop eksplisit lebih sering menjadi pilihan utama.
Contoh: menerapkan dua potongan harga secara berurutan:
from functools import reduce
def terapkan_potongan(harga, potongan):
return round(harga * (1 - potongan))
harga_awal = 200000
potongan_berurutan = [0.10, 0.05]
harga_akhir = reduce(terapkan_potongan, potongan_berurutan, harga_awal)
print(harga_akhir)Output yang Dihasilkan:
171000Bagaimana reduce sampai ke angka itu? Berikut jejaknya langkah demi langkah:
| Langkah | acc (harga) | x (potongan) | round(acc * (1 - x)) |
|---|---|---|---|
| 1 | 200000 | 0.10 | 180000 |
| 2 | 180000 | 0.05 | 171000 |
Argument ketiga harga_awal mengisi nilai awal acc. Tanpa argument tersebut, reduce memakai elemen pertama iterable sebagai titik awal. Setiap langkah memanggil terapkan_potongan(acc, x) — perhatikan urutan parameternya: accumulator selalu menjadi parameter pertama.
map dan filter vs Comprehension #
Untuk transformasi dan penyaringan sederhana, komunitas Python justru lebih memilih comprehension yang kita pelajari pada Chapter List Comprehensions:
harga = [15000, 22500, 8000]
dengan_map = list(map(lambda x: x * 2, harga))
dengan_comprehension = [x * 2 for x in harga]
print(dengan_map)
print(dengan_comprehension)
print(dengan_map == dengan_comprehension)Output yang Dihasilkan:
[30000, 45000, 16000]
[30000, 45000, 16000]
TrueKeduanya identik secara hasil. Perbandingan selera keterbacaannya:
| Aspek | map/filter + lambda | Comprehension |
|---|---|---|
| Keterbacaan | Nama function anonim, dibaca dari dalam ke luar | Nyaris seperti kalimat bahasa Inggris |
| Kombinasi transform + saring | map(f, filter(p, data)) bersarang dua lapis | Satu ekspresi: [f(x) for x in data if p(x)] |
| Posisi di idiom Python | Sekunder untuk kasus sederhana | Idiom utama |
| Unggul saat | Function sudah ada bernama, mis. map(str.strip, baris) | Hampir semua kasus sehari-hari |
Kesimpulan praktisnya: pilih comprehension untuk logika sederhana; sisakan map dan filter untuk saat function transformasi sudah tersedia sebagai nama, dan reduce untuk penggulungan yang benar-benar membutuhkannya.