Belajar dengan membaca secara berurutan

map dan filter — Mengubah atau Menyaring Array

Pelajari map yang mengubah tiap element dan filter yang hanya menyisakan element yang cocok, lengkap dengan chaining dan argument index.

Saat menghitung harga termasuk pajak dari daftar menu atau memilih produk yang stoknya masih ada, kamu sering menulis pola yang sama: deklarasikan array kosong, lalu panggil push di dalam forEach.

Artikel ini membahas map, yang mengubah element, dan filter, yang hanya menyisakan element yang memenuhi kondisi.

Mengubah Tiap Element Menjadi Array Baru — map

Misalnya kamu butuh daftar harga menu kafe yang sudah ditambah pajak. Hasilnya berupa array dengan urutan yang sama seperti 3 item aslinya, hanya harganya yang berganti. Menghitung harga satu per satu bisa kamu tulis dengan forEach, tapi untuk mengumpulkan hasilnya kamu harus menyiapkan array sendiri dan mengurusnya sampai loop selesai.

Method array map (method yang meneruskan tiap element ke callback lalu mengembalikan array baru berisi return value-nya secara berurutan) mengurus dua hal sekaligus: menyiapkan array penampung hasil dan menjalankan perulangannya. Function yang kamu berikan cukup berisi cara mengubah 1 element, lalu mengembalikan hasilnya.

const menuItems = [
  { name: "Kopi Tubruk", price: 480 },
  { name: "Caffe Latte", price: 540 },
  { name: "Cheesecake", price: 620 },
];

// Function-nya cukup mengubah 1 item
const toTaxIncluded = (item) => Math.floor(item.price * 1.1);

// toTaxIncluded dipanggil sekali untuk tiap element, dan return value-nya mengisi array baru
const taxIncluded = menuItems.map(toTaxIncluded);
console.log(taxIncluded.join(", "));   // 528, 594, 682
console.log(taxIncluded.length);       // 3
console.log(menuItems.length);         // 3
Value yang Dikembalikan Masuk ke Posisi yang Sama
Hanya 1 function:toTaxIncludedmenuItemsindex 0: 480menuItemsindex 1: 540menuItemsindex 2: 620480 × 1.1 →return 528540 × 1.1 →return 594620 × 1.1 →return 682taxIncludedindex 0taxIncludedindex 1taxIncludedindex 2
Ketiga return value masuk ke taxIncluded dengan urutan yang sama seperti element aslinya. map tidak mengubah jumlah element, hanya value-nya.

map hanya menyerahkan element ke callback satu per satu, lalu menaruh value yang kembali ke array baru. Karena itu, jumlah element-nya tidak mungkin berubah. Untuk menyaring array, yang memang mengubah jumlah element, kamu butuh method lain.

forEach Tidak Memberikan Return Value

forEach hanya memanggil function yang kamu berikan dan tidak mengumpulkan return value-nya. Yang dikembalikan selalu undefined, jadi kalau kamu menulis const list = menuItems.forEach(toTaxIncluded);, list tetap undefined. Kalau kamu ingin hasilnya berupa array, pakai map.

Ubah produk sebuah toko roti menjadi daftar harga diskon dan daftar nama produk. bakeryItems sudah dideklarasikan.

① Buat array salePrices berisi harga diskon (price dikali 0.8, lalu dibulatkan ke bawah).

② Tampilkan salePrices yang digabung dengan ", ".

③ Buat array yang hanya berisi nama produk, lalu tampilkan dengan digabung " / ".

④ Tampilkan price dari item pertama di bakeryItems.

(Kalau kodenya berjalan dengan benar, penjelasan akan muncul.)

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menyisakan Element yang Cocok Saja — filter dan Jumlah Element yang Tersisa

Misalnya kamu ingin menampilkan hanya buku yang stoknya masih ada. map tidak mengubah jumlah element, jadi tidak bisa dipakai untuk membuang buku yang stoknya habis, dan kamu kembali lagi menulis if di dalam forEach lalu memanggil push.

filter (method yang mengembalikan array baru yang hanya berisi element yang membuat callback mengembalikan true) menangani penyaringan seperti ini. Function yang kamu berikan menerima element, lalu mengembalikan boolean yang menentukan apakah element itu disimpan atau tidak.

const books = [
  { title: "SQL Praktis", stock: 0 },
  { title: "Dasar Jaringan", stock: 5 },
  { title: "Linux Bergambar", stock: 2 },
];

// Buat function yang mengembalikan boolean: disimpan atau tidak
const isInStock = (book) => book.stock > 0;

// Hanya element yang mengembalikan true yang masuk ke array baru
const available = books.filter(isInStock);
console.log(available.length);      // 2
console.log(available[0].title);    // Dasar Jaringan
console.log(books.length);          // 3
Element yang Tersisa Bergeser ke Depan
books index 0stok 0stock > 0 bernilaifalseTidak masukke availablebooks index 1stok 5stock > 0 bernilaitrueavailableindex 0books index 2stok 2stock > 0 bernilaitrueavailableindex 1
Hanya 2 item yang mengembalikan true yang masuk ke available. Jumlahnya berkurang sebanyak element yang dibuang, dan element yang tersisa bergeser ke depan untuk mengisi celahnya.

Dari available, yang bisa kamu baca hanya posisi setelah bergeser; index tiap item di books tidak ikut tersimpan. Cara memakai posisi aslinya dibahas di bagian akhir artikel ini. Tabel di bawah merangkum bagaimana ketiga method memakai return value dari function yang kamu berikan.

MethodReturn value callbackJumlah element array hasilnya
mapMasuk ke array baruSama dengan array asli
filterKalau true, element-nya disimpanSama dengan array asli atau lebih sedikit
forEachDiabaikanTidak membuat array (return undefined)

Kurung Kurawal Butuh return

Kalau body-nya kamu tulis di dalam kurung kurawal, seperti (book) => { book.stock > 0 }, return value-nya adalah undefined selama kamu tidak menulis return. undefined itu falsy, jadi tidak ada element yang disimpan dan hasilnya array kosong. Untuk pengecekan 1 baris, tulis tanpa kurung kurawal.

Pisahkan daftar produk toko tanaman hias online berdasarkan ukuran pot. plants sudah dideklarasikan.

① Buat array largePots yang hanya berisi produk pot besar, lalu tampilkan jumlahnya.

② Tampilkan nama produk yang ada di largePots, digabung dengan ", ".

③ Buat array smallPots yang hanya berisi produk pot kecil, lalu tampilkan nama produknya dengan digabung ", ".

④ Tampilkan jumlah element di plants.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Saring Dulu, Baru Ubah — Menyambung filter dan map

Misalnya kamu ingin mengubah kursus yang sudah dipublikasikan saja menjadi string untuk ditampilkan. Kamu bisa menyimpan hasil filter ke variable lalu memanggil .map(...) pada variable itu di baris berikutnya, tapi artinya kamu memberi nama pada array perantara yang tidak akan dipakai lagi.

filter juga mengembalikan array, jadi kamu bisa langsung memanggil .map(...) pada return value-nya. Cara menyambung pemanggilan method seperti ini disebut chaining (memanggil method berikutnya pada return value method sebelumnya).

const courses = [
  { title: "Pengenalan Git", minutes: 45, published: true },
  { title: "Latihan SQL", minutes: 90, published: false },
  { title: "Dasar Linux", minutes: 60, published: true },
];

// Sisakan yang sudah dipublikasikan, lalu ubah hasilnya menjadi string untuk ditampilkan
// Tanda . di awal baris memanggil method pada hasil baris sebelumnya (tetap 1 expression)
const labels = courses
  .filter((course) => course.published)   // published sudah berupa boolean, jadi langsung dikembalikan
  .map((course) => `${course.title} (${course.minutes} menit)`);

console.log(labels.join(" / "));
// Pengenalan Git (45 menit) / Dasar Linux (60 menit)
console.log(labels.length);    // 2
console.log(courses.length);   // 3
Tiga Array dalam Satu Chain
courses3 objectArray aslitetap 3.filter(...)2 objectTidakdiberi nama.map(...)2 stringDisimpandi labels
.map membaca array yang dikembalikan filter tanpa array itu pernah diberi nama. Tiap langkah dalam chain membuat 1 array baru.

Kalau ingin memeriksa hasil perantaranya, simpan hasil filter ke variable, tampilkan dengan console.log, lalu panggil .map(...) pada variable itu. Setelah selesai memeriksa, kamu bisa menyatukannya kembali menjadi chain.

Semua peserta mendapat tambahan 5 poin dari kelas susulan. Bandingkan nilai setelah tambahan dengan batas lulus 75. records sudah dideklarasikan.

① Dengan chaining, buat array passedScores yang menambah 5 poin ke nilai semua peserta, lalu hanya menyisakan nilai 75 ke atas.

② Tampilkan passedScores yang digabung dengan ", ".

③ Tampilkan score dari item kedua di records.

④ Dengan chaining, ambil nama peserta yang nilainya mencapai 75 ke atas setelah tambahan, lalu tampilkan dengan digabung " / ".

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Mengetahui Posisi Element — index di Callback

Misalnya kamu ingin menambahkan peringkat seperti "#1" dan "#2" ke daftar ranking. Element-nya sendiri tidak menyimpan peringkat, jadi kamu mungkin tergoda menaruh variable penghitung di luar callback lalu menambahnya dengan 1 setiap kali callback dipanggil.

map dan filter memberikan element sebagai argument pertama callback, dan posisi element itu (index-nya, dihitung dari 0) sebagai argument kedua. Argument dicocokkan berdasarkan urutan, jadi walaupun kamu hanya butuh index-nya, parameter pertama tetap harus ditulis. Kalau parameter kedua itu kamu beri nama index, kamu bisa memakainya untuk menampilkan peringkat sekaligus untuk mengecek apakah sebuah element termasuk beberapa element pertama.

const ranking = ["Earbuds Wireless", "Power Bank", "Stand HP", "USB Hub"];

// Argument kedua adalah posisi yang dihitung dari 0
const lines = ranking.map((item, index) => `#${index + 1}: ${item}`);
console.log(lines.join("\n"));
// #1: Earbuds Wireless
// #2: Power Bank
// #3: Stand HP
// #4: USB Hub

// Callback filter juga menerima 2 argument yang sama
const topThree = ranking.filter((item, index) => index < 3);
console.log(topThree.length);   // 3
Dua Cara Memakai index yang Sama
map menerima(item, index)4 item menerimaindex 0 sampai 3index + 1 masukke stringTetap 4 item,kini berperingkatfilter menerima(item, index)Sama seperti map,0 sampai 3Disimpankalau index < 3Tinggal 3 item,value-nya tetap
Kedua callback menerima posisi yang dihitung dari 0 sebagai argument kedua. map memasukkan posisi itu ke value baru, sedangkan filter memakainya untuk menentukan element mana yang disimpan.

index yang diterima filter adalah posisi di array asli. Element yang disimpan memang bergeser ke depan setelahnya, tapi itu tidak memengaruhi pengecekan, jadi index < 3 berarti 3 item pertama di array asli.

Halaman artikel pilihan menampilkan artikel sesuai urutan rekomendasi. articles dan viewCounts sudah dideklarasikan, dan viewCounts berisi jumlah view tiap artikel dengan urutan yang sama.

① Dengan memakai viewCounts, buat array string berbentuk "Judul (N kali dilihat)", lalu tampilkan satu per baris.

② Sisakan hanya artikel yang dilihat 5000 kali atau lebih, lalu tampilkan dengan digabung ", ".

③ Sisakan hanya artikel di peringkat genap, seperti #2 dan #4, lalu tampilkan dengan digabung ", ".

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Setelah kamu menjalankan prices.map((price) => price * 2), apa yang terjadi pada prices yang asli?

Soal 2Pada courses.filter(isPublished).map(toLabel), array mana yang dibaca map?

Soal 3Di callback ranking.map((item, index) => ...), apa yang diterima index?