Array Reduce JavaScript: Sintaks dan Contoh Penggunaan
reduce() merupakan method array di JavaScript yang mengeksekusi fungsi callback pada setiap elemen array, nilai hasil kalkulasi pada elemen sebelumnya digunakan untuk melakukan kalkulasi pada elemen berikutnya.
Setelah menjalankan fungsi callback untuk semua elemen array, method ini menghasilkan nilai tunggal.
Kasus yang paling mudah dipahami adalah ketika kita ingin menjumlahkan semua elemen array angka.
Method ini memang terlihat agak rumit pada awalnya, tapi jangan khawatir karena ini akan kita pelajari secara perlahan mulai dari sintaks hingga contoh penggunaannya.
Sintaks
// arrow function
reduce((nilaiSebelumnya, nilaiSaatIni, indexSaatIni, array) => { ... }, nilaiAwal)
// callback function
reduce(callbackFn, nilaiAwal)
Parameter
-
callbackFn: fungsi callback yang dieksekusi untuk setiap elemen array. Menerima empat argumen berikut:nilaiSebelumnya: nilai yang dikembalikan dari fungsi callback sebelumnya.nilaiSaatIni: nilai elemen array saat ini.indeksSaatIni(opsional): indeks elemen saat ini.array(opsional): array sumber.
-
nilaiAwal(opsional):Jika ditentukan, nilai ini akan digunakan oleh
nilaiSebelumnyasaat pertama kali callback dipanggil, dannilaiSaatIniakan berisi nilai elemen pertama pada array.Jika tidak,
nilaiSebelumnyaakan menggunakan elemen pertama array dannilaiSaatInimenggunakan elemen kedua.
Nilai Kembalian
Mengembalikan nilai yang dihasilkan oleh fungsi callback sampai akhir elemen array.
Method ini dapat mengembalikan kesalahan TypeError jika array tidak memiliki elemen dan nilaiAwal tidak disediakan.
Cara Kerja reduce()
Mari kita gunakan array sederhana untuk memahami cara kerja reduce().
Untuk mengurangi distraksi, saya tidak akan membahas indeksSaatIni dan array karena indeksSaatIni hanya diinisialisasi dengan indeks elemen saat ini yang sedang diiterasi/diulang.
Sedangkan array diinisialisasi dengan array sumber.
Keduanya bersifat opsional, boleh kita hilangkan.
Yang terpenting adalah memahami nilai dari argumen nilaiSebelumnya dan nilaiSaatIni.
Tanpa nilaiAwal
Mari kita gunkaan contoh sederhana, dalam kasus kali ini kita akan menjumlahkan semua elemen pada array arrAngka, tanpa nilaiAwal.
const arrAngka = [1, 2, 3, 4, 5];
const result = arrAngka.reduce((nilaiSebelumnya, nilaiSaatIni) => {
return nilaiSebelumnya + nilaiSaatIni;
});
console.log(result); // 15
Dalam kasus ini fungsi callback dipanggil sebanyak empat kali, berikut langkah-langkahnya:
| Pengulangan callback | nilaiSebelumnya | nilaiSaatIni | Nilai Kembalian |
|---|---|---|---|
| Pertama | 1 | 2 | 3 |
| Kedua | 3 | 3 | 6 |
| Ketiga | 6 | 4 | 10 |
| Keempat | 10 | 5 | 15 |
Perhatikan gambar berikut.
Yang perlu diperhatikan di sini, ketika callback dipanggil pertama kali, nilai dari nilaiSebelumnya akan menggunakan nilai dari elemen pertama array, 1.
Sedangkan nilaiSaatIni menggunakan nilai elemen kedua dari array, 2.
Oleh karena itu, pada iterasi pertama fungsi callback menghasilkan nilai 3 hasil dari penjumlahan nilaiSebelumnya + nilaiSaatIni (1 + 2).
Karena masih ada elemen array, maka nilai ini tidak langsung dikembalikan, melainkan diinisialisasi ke nilaiSebelumnya untuk pemanggilan callback berikutnya.
Jadi, pada pengulangan callback kedua, nilaiSebelumnya sekarang bernilai 3 sedangkan nilaiSaatIni bergeser menggunakan elemen array berikutnya yaitu 3.
Singkatnya, tanpa nilaiAwal:
Pada panggilan callback pertama,
nilaiSebelumnyamenggunakan nilai elemen pertam array, sedangkannilaiSaatInimenggunakan elemen kedua.
Dengan nilaiAwal
Mari kita gunakan array yang sama, tapi sekarang kita inisialisasi nilaiAwal dengan 5.
const arrAngka = [1, 2, 3, 4, 5];
const result = arrAngka.reduce((nilaiSebelumnya, nilaiSaatIni) => {
return nilaiSebelumnya + nilaiSaatIni;
}, 5);
console.log(result); // 20
Dalam kasus kali ini fungsi callback dipanggil sebanyak lima kali, berikut langkah-langkahnya:
| Pengulangan callback | nilaiSebelumnya | nilaiSaatIni | Nilai Kembalian |
|---|---|---|---|
| Pertama | 5 | 1 | 6 |
| Kedua | 6 | 2 | 8 |
| Ketiga | 8 | 3 | 11 |
| Keempat | 11 | 4 | 15 |
| Kelima | 15 | 5 | 20 |
Perhatikan gambar berikut.
Yang perlu diperhatikan di sini, nilai dari nilaiSebelumnya tidak lagi menggunakan
elemen pertama array, melainkan nilai dari nilaiAwal yaitu 5.
Sedangkan nilaiSaatIni menggunakan elemen pertama array. Oleh karena itu menghasilkan nilai 20.
Selebihnya sama dengan contoh sebelumnya.
Jadi, dengan nilaiAwal:
Pada panggilan callback pertama,
nilaiSebelumnyamenggunakan nilai darinilaiAwal, sedangkannilaiSaatInimenggunakan elemen pertama array.
Contoh
Menjumlahkan Nilai Objek Dalam Array
Mari kita gunakan contoh yang agak kompleks.
Kita di sini ingin mengetahui berapa total nilai mahasiswa jika dijumlahkan.
const mahasiswa = [
{ nama: 'ucup', nilai: 80 },
{ nama: 'budi', nilai: 90 },
{ nama: 'bambang', nilai: 75 },
];
const totalNilai = mahasiswa.reduce((nilaiSebelumnya, nilaiSaatIni) => {
return nilaiSebelumnya + nilaiSaatIni.nilai;
}, 0);
console.log(totalNilai); // 245
Kita disini perlu mengisi nilaiAwal dengan 0, kalau tidak, pada panggilan callback pertama, nilaiSebelumnya akan diinisialisasi dengan elemen pertama pada array yaitu objek { nama: 'ucup', nilai: 80 }.
Karena nilaiAwal ditentukan, nilaiSaatIni akan menggunakan elemen pertama pada array yaitu { nama: 'ucup', nilai: 80 }.
Oleh karena itu di dalam badan fungsi kita perlu menggunakan notasi titik untuk mengakses nilai dari properti nilai (nilaiSaatIni.nilai).
Menyisipkan Objek ke Array
Saat membuat aplikasi kadang kita perlu mengatur ulang struktur array, tujuannya tentu saja agar lebih terstruktur.
Misalnya, ini array yang kita miliki sekarang.
['reza', 'ucup', 'udin'];
Di sini kita ingin memasukkan setiap elemen array ke dalam objek berisi properti name untuk masing-masing elemen saat ini dan gender kita isi dengan male.
Jadi, ini yang kita inginkan.
[
{ name: 'reza', gender: 'male' },
{ name: 'ucup', gender: 'male' },
{ name: 'udin', gender: 'male' },
];
Masalah ini sebetulnya bisa diselesaikan dengan map, tapi inilah jika kita menggunakan reduce.
const usersMale = ['reza', 'ucup', 'udin'];
const refactUsersMale = usersMale.reduce((prev, user) => {
return [
...prev,
{
name: user,
gender: 'male',
},
];
}, []);
console.log(refactUsersMale);
/* output:
[
{ name: 'reza', gender: 'male' },
{ name: 'ucup', gender: 'male' },
{ name: 'udin', gender: 'male' }
]
*/
Contoh kali ini ada yang berbeda dari sebelumnya, kali ini nilaiAwal disi dengan array kosong ([]).
Ya, kita bisa mengisi nilaiAwal dengan nilai apa pun termasuk angka, string, array, objek dan sebagainya.
...prev (titik tiga) adalah sintaks spread, jika Anda belum mempelajarinya, jangan khawatir, Anda bisa kembali ke sini kapan saja.
Mengganti filter().map() dengan reduce()
reduce bisa kita gunakan sebagai pengganti filter().map() yang lebih efisien.
Misalnya, kita memiliki array sebagai berikut.
[1, 2, 3, 4, 6];
Kita ingin memfilter bilangan genap ([2, 4, 6]) lalu kita kalikan semuanya dengan 2, sehingga hasilnya seperti ini.
[4, 8, 12];
Kita tidak bisa menangani kasus seperti ini hanya menggunakan map, karena callback map harus mengembalikan nilai, kalau tidak, nilai undefined dikembalikan.
Apalagi jika hanya menggunkan filter, tidak bisa.
Mereka berdua saling melengkapi.
Jadi, inilah jika kita menggunakan filter().map().
const numbers = [1, 2, 3, 4, 6];
const result = numbers.filter((num) => num % 2 === 0).map((num) => num * 2);
console.log(result); // [ 4, 8, 12 ]
Tidak ada yang salah dengan metode di atas. Tapi, ini kurang efisien.
Perulangan atau callback dieksekusi sebanyak 8 kali, bukan 10 kali, apalagi 5 kali hanya karena elemennya ada 5.
5 kali untuk filter, dan 3 kali untuk map.
Kenapa map hanya 3 kali? Karena filter mengembalikan array berisi 3 elemen.
Kita bisa mengatasi ini dengan reduce agar perulangan hanya dilakukan sebanyak 5 kali.
Jadi, inilah jika kita menggunakan reduce.
const numbers = [1, 2, 3, 4, 6];
const result = numbers.reduce((prev, curr) => {
if (curr % 2 === 0) {
prev.push(curr * 2);
}
return prev;
}, []);
console.log(result); // [ 4, 8, 12 ]