map dan filter

Transformasi dan pemilihan data array tanpa perulangan manual.

Daftar isi

Metode map dan filter mengolah array dengan mengoper satu fungsi kecil ke setiap elemennya, tanpa perulangan yang ditulis manual. Setelah topik ini, transformasi sebuah array menjadi array baru berukuran sama dan pemilihan butir yang lolos suatu syarat mengikuti pola yang baku. Topik ini juga menyandingkan kedua metode dengan perulangan manual yang setara, lalu menegaskan sifat terpentingnya, yaitu hasil kerja keduanya selalu array baru dan array asalnya tidak tersentuh.

map, satu masukan satu keluaran#

Metode map memanggil sebuah fungsi untuk setiap elemen array lalu mengumpulkan nilai baliknya menjadi array baru, dengan panjang yang persis sama seperti array asalnya. Fungsi yang dioper seperti ini disebut callback, yakni fungsi yang diberikan sebagai argumen agar dapat dipanggil kembali oleh kode lain. Karena satu elemen masuk dan satu keluaran keluar pada posisi yang sama, map dipakai untuk mengubah bentuk data, bukan untuk membuang atau menambah butir.

Contoh berikut mengonversi suhu Celcius ke Fahrenheit. Callback (c) => (c * 9) / 5 + 32 dijalankan empat kali, satu kali untuk setiap elemen, dan hasilnya ditampung di array baru bernama fahrenheit.

js Contoh: map mengubah setiap suhu ke Fahrenheit
const celcius = [26, 30, 24, 28];
const fahrenheit = celcius.map((c) => (c * 9) / 5 + 32);

console.log(celcius);
console.log(fahrenheit);
text Keluaran
[ 26, 30, 24, 28 ]
[ 78.8, 86, 75.2, 82.4 ]

Angkanya mudah diperiksa ulang, misalnya 26 dikali 9 dibagi 5 ditambah 32 menghasilkan 78.8. Urutan keluaran mengikuti urutan masukan karena map menelusuri array dari indeks 0 sampai terakhir. Array kosong juga menghasilkan array kosong, karena tidak ada elemen yang perlu dikonversi.

filter, memilih yang lolos uji#

Metode filter mengembalikan array baru. Isinya hanya elemen yang lolos syarat, yaitu elemen yang membuat callback menghasilkan nilai benar. Callback pada filter bertugas sebagai uji lulus atau gagal, bukan sebagai pengubah bentuk, sehingga isi elemennya tidak pernah dimodifikasi. Panjang array hasilnya paling banyak sama dengan array asal dan bisa jauh lebih pendek bila banyak butir tidak lolos.

js Contoh: filter memilih nilai yang mencukupi
const nilai = [78, 92, 65, 84, 71, 90];
const lulus = nilai.filter((n) => n >= 75);

console.log(lulus);
console.log(`array awal: ${nilai.length} butir, array lulus: ${lulus.length} butir`);
text Keluaran
[ 78, 92, 84, 90 ]
array awal: 6 butir, array lulus: 4 butir

Dari enam nilai ujian, empat yang mencapai batas minimal 75 dan semuanya terbawa dengan urutan yang tetap terjaga. Nilai 65 dan 71 tidak dihapus dari array nilai, melainkan hanya tidak ikut masuk ke array lulus. Bila tidak ada satu pun yang lolos, hasilnya array kosong, dan itu adalah jawaban yang sah untuk pertanyaan seleksi tersebut.

Tiga parameter pada callback#

Callback map dan filter dapat menerima hingga tiga parameter, yaitu nilai elemen, indeks elemen, dan array sumbernya. Parameter kedua dan ketiga ditulis hanya bila dibutuhkan, sehingga bentuk satu parameter seperti (c) => ... adalah bentuk yang paling umum. Parameter indeks berguna saat posisi ikut menjadi data, misalnya untuk memberi nomor urut pada setiap baris.

js Contoh: nomor urut lewat parameter kedua
const nilai = [78, 92, 65, 84];
const berlabel = nilai.map((n, i) => `${i + 1}. ${n}`);

console.log(berlabel.join("\n"));
text Keluaran
1. 78
2. 92
3. 65
4. 84

Ekspresi i + 1 menggeser indeks yang mulai dari 0 menjadi nomor urut yang mulai dari 1. Bentuk itu lebih wajar bagi pembaca daftar. Parameter ketiga, yaitu array sumber, dipakai lebih jarang, misalnya untuk membandingkan elemen dengan tetangganya di dalam callback. Sebagian besar callback memang hanya memakai parameter pertama, dan itu wajar karena parameter yang tidak ditulis tidak pernah diisi.

Berdampingan dengan perulangan manual#

Cara paling jelas memahami map dan filter adalah melihat tugas yang sama dikerjakan dua kali, satu dengan perulangan manual dan satu dengan kedua metode tersebut. Berkas berikut mencari siswa yang lulus, mengambil namanya, lalu menuliskannya huruf besar dengan kedua gaya. Keluaran kedua versinya diletakkan berdampingan agar kesetaraannya terlihat.

js berdampingan.js
// Tujuan yang sama, dua cara: nama siswa yang lulus, ditulis huruf besar
const ujian = [
  { nama: "Ali", nilai: 78 },
  { nama: "Budi", nilai: 92 },
  { nama: "Citra", nilai: 65 },
  { nama: "Dewi", nilai: 84 },
];

// cara perulangan manual
const manual = [];
for (const siswa of ujian) {
  if (siswa.nilai >= 75) {
    manual.push(siswa.nama.toUpperCase());
  }
}

// cara filter lalu map
const metode = ujian
  .filter((s) => s.nilai >= 75)
  .map((s) => s.nama.toUpperCase());

console.log(`manual : ${manual.join(", ")}`);
console.log(`metode : ${metode.join(", ")}`);
text Keluaran
manual : ALI, BUDI, DEWI
metode : ALI, BUDI, DEWI
bash
# jalankan berkas contoh dari direktori topik
node berdampingan.js
text Keluaran
manual : ALI, BUDI, DEWI
metode : ALI, BUDI, DEWI

Keluaran blok bash sama persis karena perintahnya menjalankan berkas yang sama. Kedua versi menghasilkan ALI, BUDI, DEWI, tetapi pembacaannya berbeda. Pada versi manual, maksud program tersimpan di antara tanda kurung, variabel penampung, dan push, sehingga harus ditelusuri baris demi baris. Pada versi filter dan map, maksudnya terbaca dari nama metodenya, seleksi dulu, lalu ubah bentuk. Perulangan manual tetap tepat untuk tugas yang tidak sepadan satu lawan satu, misalnya tugas yang mengumpulkan hasil menjadi satu nilai.

Array hasil selalu baru#

map dan filter tidak pernah mengubah array asalnya, keduanya selalu membuat dan mengembalikan array baru. Sifat ini penting karena array lama tetap utuh untuk keperluan lain, misalnya dicetak ulang atau difilter lagi dengan syarat berbeda. Konsekuensinya, nilai baliknya harus ditampung atau diteruskan, karena hasil yang tidak ditampung akan terbuang begitu saja.

js Contoh: array asal tetap utuh
const awal = [26, 30, 24];
const dipanaskan = awal.map((c) => c + 2);
const panas = awal.filter((c) => c > 25);

console.log(awal);
console.log(dipanaskan);
console.log(panas);
text Keluaran
[ 26, 30, 24 ]
[ 28, 32, 26 ]
[ 26, 30 ]

Array awal tetap berisi [26, 30, 24] setelah dua operasi, sementara dipanaskan dan panas adalah dua array baru yang masing-masing memegang hasil transformasi dan seleksinya. Satu kehalusan perlu dicatat: untuk array yang berisi object, yang berpindah ke array baru adalah referensinya, bukan salinan objectnya, sehingga mengubah properti object di array hasil ikut mengubah object di array asal. Bagaimanapun, panjang dan urutan array barunya tetap terpisah dari array sumber.

Kesalahan umum#

  1. Lupa return pada callback berkurung kurawal. Arrow function dengan badan {} tidak otomatis mengembalikan nilai, sehingga map menghasilkan array penuh undefined dan filter kehilangan syarat ujinya. Pakai bentuk satu ekspresi tanpa kurung kurawal untuk callback pendek, atau tulis return secara eksplisit di dalam badannya. Kesalahan ini sering tidak memunculkan error, karena keluarannya hanya tampak kosong atau tidak lengkap.
  2. Mengira array asal ikut berubah. Hasil map atau filter yang tidak ditampung hilang begitu pernyataannya selesai, sedangkan variabel lama tetap berisi data awal. Simpan nilai baliknya ke variabel baru, misalnya const lulus = nilai.filter((n) => n >= 75), dan jangan menimpa nama array lama agar pembaca tidak berasumsi isinya berubah.
  3. Memakai map hanya untuk mencetak. Bila callback mengembalikan nilai yang tidak pernah dipakai, array hasilnya langsung terbuang dan maksud kodenya menyesatkan bagi pembaca berikutnya. Untuk tugas efek samping semacam ini, perulangan biasa menyatakan maksud dengan lebih jelas, sedangkan transformasi yang hasilnya dipakai tetap ditulis dengan map.

Ringkasan#

  • map menjalankan callback pada setiap elemen dan mengembalikan array baru dengan panjang yang sama seperti array asal.
  • filter mengembalikan array baru berisi elemen yang lolos syarat callback, dengan urutan tetap terjaga.
  • Callback keduanya dapat menerima nilai, indeks, dan array sumber, dipakai secukupnya sesuai kebutuhan.
  • Array hasil selalu baru dan array asal tidak berubah, sehingga nilai baliknya wajib ditampung agar tidak terbuang.

Referensi#