15 Desember 2021

Metode *array*

Array menyediakan begitu banyak metode. Untuk mempermudah, dalam bab ini metode-metode tersebut dibagi menjadi beberapa kelompok.

Menambahkan/menghapus item

Kita sudah tahu metode-metode yang menambahkan dan menghapus item dari bagian awal atau akhir array:

  • arr.push(...items) – menambahkan item ke bagian akhir,
  • arr.pop() – mengekstrak sebuah item dari bagian akhir,
  • arr.shift() – mengekstrak sebuah item dari bagian awal,
  • arr.unshift(...items) – menambahkan item ke bagian awal.

Berikut ini ada beberapa metode lainnya.

splice

Bagaimana cara untuk menghapus sebuah elemen dari array?

Array merupakan objek, jadi kita bisa coba menggunakan delete:

let arr = ["I", "go", "home"];

delete arr[1]; // menghapus "go"

alert( arr[1] ); // undefined

// kini arr = ["I",  , "home"];
alert( arr.length ); // 3

Elemen tersebut telah dihapus, tetapi array itu masih memiliki 3 elemen, kita bisa melihat bahwa arr.length == 3.

Hal itu alami, karena delete obj.key menghilangkan sebuah nilai berdasarkan key. Itulah yang dilakukannya. Tidak masalah bagi objek. Tapi untuk array kita biasanya ingin elemen yang tersisa untuk bergeser dan mengisi ruang yang dikosongkan tadi. Kita ingin memiliki sebuah array yang lebih pendek sekarang.

Jadi, metode khusus harus digunakan.

Metode arr.splice(start) adalahs sebuah fungsi serbaguna untuk array. Splice bisa melakukan banyak hal: memasukkan, menghilangkan serta mengganti elemen.

Sintaksnya yakni:

arr.splice(start[, deleteCount, elem1, ..., elemN])

Dimulai dari posisi index: menghapus elemen deleteCount dan kemudian memasukkan elem1, ..., elemN di tempatnya masing-masing. Mengembalikan array yang tersusun atas elemen yang dihapus.

Metode ini mudah untuk dipahami melalui contoh.

Mari mulai dengan penghapusan:

let arr = ["I", "study", "JavaScript"];

arr.splice(1, 1); // dari indeks 1 menghapus 1 elemen

alert( arr ); // ["I", "JavaScript"]

Mudah, kan? Mulai dari indeks 1 metode ini menghilangkan elemen di indeks 1.

Dalam contoh selanjutnya kita menghilangkan 3 element dan menggantinya dengan 2 elemen lain:

let arr = ["I", "study", "JavaScript", "right", "now"];

// menghilangkan 3 elemen pertama dan menggantinya dengan yang lain
arr.splice(0, 3, "Let's", "dance");

alert( arr ) // sekarang ["Let's", "dance", "right", "now"]

Di sini kita dapat melihat bahwa splice mengembalikan array yang berisi elemen terhapus:

let arr = ["I", "study", "JavaScript", "right", "now"];

// menghilangkan 2 elemen pertama
let removed = arr.splice(0, 2);

alert( removed ); // "I", "study" <-- array yang berisi elemen-elemen yang dihapus

Metode splice juga mampu memasukkan elemen tanpa menghilangkan elemen apapun yang ada sebelumnya. Untuk itu kita perlu mengatur deleteCount menjadi 0:

let arr = ["I", "study", "JavaScript"];

// dari indeks 2
// menghapus 0
// kemudian masukkan "complex" dan "language"
arr.splice(2, 0, "complex", "language");

alert( arr ); // "I", "study", "complex", "language", "JavaScript"
Indeks berangka negatif diperbolehkan

Di sini dan di metode array lainnya, indeks (berangka) negatif diperbolehkan. Indeks-indeks tersebut menspesifikasikan posisi dari bagian akhir sebuah array, seperti ini:

let arr = [1, 2, 5];

// dari indeks -1 (satu langkah dari bagian akhir)
// menghaous 0 element,
// lalu memasukka 3 dan 4
arr.splice(-1, 0, 3, 4);

alert( arr ); // 1,2,3,4,5

slice

Metode arr.slice lebih sederhana daripada metode serupa sebelumnya yakni arr.splice.

Sintaksnya adalah:

arr.slice([start], [end])

Metode ini mengembalikan sebuah sebuah array baru hasil salinan semua item yang ada dari indeks start hingga end (indeks end tidak termasuk). Baik start maupun end bisa saja negatif, dalam kasus tersebut posisi dari bagian akhir array sudah diasumsikan/diperkirakan.

Mirip dengan metode string str.slice, namun membuat subarray bukan substring.

Contohnya:

let arr = ["t", "e", "s", "t"];

alert( arr.slice(1, 3) ); // e,s (disalin dari 1 sampai 3)

alert( arr.slice(-2) ); // s,t (disalin dari -2 sampai bagian akhir)

Kita juga bisa memanggil metode tersebut tanpa argumen: arr.slice() membuat sebuah salinan dari arr. Cara demikian seringkali digunakan untuk mendapatkan sebuah salinan untuk transformasi yang lebih jauh tanpa mempengaruhi array yang asli.

concat

Metode arr.concat membuat sebuah array baru yang sudah termasuk nilai-nilai dari array lainnya serta item-item tambahan.

Sintaksnya sebagai berikut:

arr.concat(arg1, arg2...)

Sintaks tersebut menerima berapapun argumen – bisa jadi array atau nilai.

Hasilnya adalah sebuah array yang berisi item dari arr, kemudian arg1, arg2 dan sebagainya.

Jika sebuah argumen argN adalah sebuah array, makan semua elemennya akan disalin. Jika tidak, argumen itu sendiri yang akan disalin.

Sebagai contoh:

let arr = [1, 2];

// membuat sebuah array dari: arr dan [3,4]
alert( arr.concat([3, 4]) ); // 1,2,3,4

// membuat sebuah array dari: arr dan [3,4] dan [5,6]
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6

// membuat sebuah array dari: arr dan [3,4], lalu menambahkan nilai 5 dan 6
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

Normalnya, metode ini hanya menyalin elemen-elemen dari array. Objek lainnya, bahkan jika objek-objek tersebut terlihat seperti array, akan ditambahkan secara keseluruhan:

let arr = [1, 2];

let arrayLike = {
  0: "something",
  length: 1
};

alert( arr.concat(arrayLike) ); // 1,2,[oobjek Object]

…Tetapi jika sebuah objek mirip array memiliki sebuah properti khusus Symbol.isConcatSpreadable, maka objek tersebut diperlakukan sebagai sebuah array dengan concat: elemennya ditambahkan:

let arr = [1, 2];

let arrayLike = {
  0: "something",
  1: "else",
  [Symbol.isConcatSpreadable]: true,
  length: 2
};

alert( arr.concat(arrayLike) ); // 1,2,something,else

Iterate: forEach

Metode arr.forEach membuat kita dapat menjalankan sebuah fungsi untuk setiap elemen yang ada di dalam array.

Sintaksnya:

arr.forEach(function(item, index, array) {
  // ... do something with item
});

Sebagai contoh, kode berikut ini menampilkan tiap elemen dalam array:

// untuk setiap (for each) elemen memanggil alert
["Bilbo", "Gandalf", "Nazgul"].forEach(alert);

Dan kode ini lebih rinci tentang posisi elemen-elemen tersebut dalam array yang dituju:

["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
  alert(`${item} is at index ${index} in ${array}`);
});

Hasil dari fungsi tersebut (jika mengembalikan sesuatu) dibuang dan diabaikan.

Mencari dalam array

Kini mari membahas metode-metode yang bertugas mencari dalam array.

indexOf/lastIndexOf dan includes

Metode arr.indexOf, arr.lastIndexOf dan arr.includes memiliki sintaks yang sama dan pada dasarnya keduanya melakukan fungsi yang samahave the same syntax, namun untuk mengoperasikannya perlu ditujukan item bukan karakter:

  • arr.indexOf(item, from) – mencari item dimulai dari indeks from, dan mengembalikan indeks dimana item yang dicari itu ditemukan, jika tidak akan mengembalikan -1.
  • arr.lastIndexOf(item, from) – serupa, namun mencari dari kiri ke kanan.
  • arr.includes(item, from) – mencari item dimulai dari indeks from, mengembalkikan true jika yang dicari itu ditemukan.

Contohnya:

let arr = [1, 0, false];

alert( arr.indexOf(0) ); // 1
alert( arr.indexOf(false) ); // 2
alert( arr.indexOf(null) ); // -1

alert( arr.includes(1) ); // true

Perlu diperhatikan bahwa metode tersebut menggunakan perbandingan ===. Jadi, jika kita mencari false, metode ini akan tepat mencari false dan bukan nol.

Jika kita ingin memeriksa pencantuman, dan tidak ingin tahu indeks yang persis, maka direkomendasikan menggunakan arr.includes.

Juga, perbedaan kecil dari includes yakni metode ini menangani NaN dengan tepat, tidak seperti indexOf/lastIndexOf:

const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (seharusnya 0, tetapi tanda persamaan === tidak berfungsi pada NaN)
alert( arr.includes(NaN) );// true (benar)

find dan findIndex

Bayangkan kita memiliki sebuah array berisi objek. Bagaimana cata kita menemukan sebuah objek dengan kondisi tertentu?

Berikut ini ada metode arr.find(fn) yang dapat mudah digunakan.

Sintaksnya:

let result = arr.find(function(item, index, array) {
  // jika true dikembalikan, item dikembalikan dan pengulangan dihentinkan
  // untuk skenario palsu akan mengembalikan undefined
});

Fungsi tersebut dipanggil untuk elemen-elemen dalam array, satu sama lainnya:

  • item adalah elemen.
  • index adalah indeks elemen tersebut.
  • array adalah array itu sendiri.

Jika fungsi tersebut mengembalikan true, pencarian dihentikan, lalu item akan dikembalikan. Jika tidak ditemukan apa-apa, undefined yang dikembalikan.

Sebagai contoh, kita memiliki sebuah array berisi elemen pengguna, tiap pengguna memiliki field id dan name. Mari cari pengguna dengan id == 1:

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

let user = users.find(item => item.id == 1);

alert(user.name); // John

Pada kehidupan nayata array berisi objek adalah hal yang umum, jadi metode find sangatlah berguna.

Ingat bahwa contoh yang kami berikan untuk mencari (find) fungsi item => item.id == 1 hanya dengan satu argumen. Ini adalah hal umum, argumen lainnya pada fungsi lainnya jarang digunakan.

Metode arr.findIndex pada dasarnya sama, namun mengembalikan indeks dimana elemen tersebut ditemukan bukan elemen itu sendiri serta mengembalikan -1 ketika tidak ditemukan apapun.

filter

Metode find mencari sebuah elemen tunggal (pertama) yang akan membuat fungsi tersebut mengembalikan true.

Jika ada banyak elemen demikian, kita bisa menggunakanarr.filter(fn).

Sintaksnya mirip dengan find, tetapi filter mengembalikan array yang berisi elemen-elemen yang cocok:

let results = arr.filter(function(item, index, array) {
  // jika true item di-push ke hasil dan pengulangan berlanjut
  // mengembalikan array kosong jika tidak ditemukan apapun
});

Sebagai contoh:

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

// mengembalikan array dua user pertama
let someUsers = users.filter(item => item.id < 3);

alert(someUsers.length); // 2

Mengubah array

Mari lanjutkan ke metode-metode yang mengubah dan mengatur ulang array.

map

Metode arr.map adalah salah satu metode yang paling berguna dan paling sering digunakan.

Metode ini memanggil fungsi untuk tiap elemen di array dan mengembalikan hasilnya dalam bentuk array.

Sintaksnya yakni:

let result = arr.map(function(item, index, array) {
  // mengembalikan nilai baru, bukan item
});

Sebagai contoh, di sini kita mengubah setiap elemen menjadi panjang (length) dari string elemen tersebut:

let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6

sort(fn)

Panggilan arr.sort() menata array dalam wadah, mengubah urutan elemen yang ada.

Metode ini juga mengembalikan array yang sudah tertata, tetapi nilai yang dikembalikan biasanya diabaikan, mengingat arr itu sendiri sudah termodifikasi/diubah.

Contohnya:

let arr = [ 1, 2, 15 ];

// metode tersebut mengurutkan ulang konten arr
arr.sort();

alert( arr );  // 1, 15, 2

Apa kamu menyadari adanya keanehan dari hasil di atas?

Urutannya menjadi 1, 15, 2. Tidak benar. Tapi mengapa demikian?

Item-item tersebut diurutkan sebagai string secara pada dasarnya.

Secara harfiah, semua elemen dikonversi menjadi string untuk dibandingkan. Sedangkan pada string, berlaku pengurutan leksikograpis dan memang benar bahwa "2" > "15".

Untuk menggunakan urutan penataan kita sendiri, kita perlu memberikan sebuah fungsi sebagai argumen pada arr.sort().

Fungsi tersebut harus membandingkan dua nilai yang berubah-ubah dan mengembalikan (hasilnya):

function compare(a, b) {
  if (a > b) return 1; // if the first value is greater than the second
  if (a == b) return 0; // if values are equal
  if (a < b) return -1; // if the first value is less than the second
}

Contoh, untuk mengurutkan elemen sebagai angka:

function compareNumeric(a, b) {
  if (a > b) return 1;
  if (a == b) return 0;
  if (a < b) return -1;
}

let arr = [ 1, 2, 15 ];

arr.sort(compareNumeric);

alert(arr);  // 1, 2, 15

Kini metode tersebu berfungsi seperti yang diinginkan.

Mari berhenti sejenak dan pikirkan apa yang terjadi. arr bisa jadi array berisi apapun, benar? Array itu bisa saja berisi angka atau string atau objek atau apapun. Kita memiliki sekumpulan beberapa item. Untuk mengurutkannya, kita perlu sebuah fungsi pengurutan yang tahu bagaimana cara untuk membandingkan elemen-elemen. Setelan awalnya adalah sebuah urutan string.

Metode arr.sort(fn) mengimplementasikan sebuah algoritma pengurutan yang umum. Kita tidak perlu benar-benar tahu bagaimana algoritma itu bekerja (sebuah cara cepat/quicksort yang sudah teroptimasi sepanjang waktu). Algoritma itu akan menyusuri array, membandungkan elemen-elemennya menggunakan fungsi yang diberikan dan mengurutkan ulang elemen-elemen tersebut, yang perlu kita lakukan yakni memberikan fn yang mana akan melakukan operasi perbandingan.

Ngomong-omong, jika kita pernah ingin tahu elemen mana saja yang dibandingkan – cukup dengan cara memberi alert: