18 Januari, 2021

randomPick

Pick random element(s) from an array

const randomPick = (source = [], anyNumber = 1) => {
  if (source.length > 0) {
    let result = [];
    
    // Duplicate original array
    let poppedArray = [].concat(source);
    let currentLength = poppedArray.length;

    for (let i = 0; i < anyNumber; i++) {
      // Generate random number to pick an element inside array
      const magicNumber = Math.floor(Math.random() * (currentLength - Math.random()));

      // Slice the array so picked element won't be picked anymore
      result.push(poppedArray.splice(magicNumber, 1)[0]);

      currentLength = poppedArray.length;
    }
  
    return result;
  }
  
  return source;
}

Konteks

Terkadang kamu mau memilih satu atau beberapa elemen pada sebuah array dengan cara acak pada JavaScript. Namun fungsi tersebut tidak terdapat pada prototip Array yang bisa langsung kamu gunakan (sampai tulisan ini ditulis).

Penggunaan

Kamu bisa menggunakan kode ini dengan dua cara sesuai dengan kondisi yang dibutuhkan.

Pertama, kalau kamu cuma mau memilih satu elemen pada sebuah array maka cukup masukkan satu parameter yaitu sumber array.

// get a member from a group
// ['Belladeon', 'Eludia', 'Camilla']
randomPick(members);

Kedua, kamu bisa mengambil beberapa elemen secara random dengan memasukkan jumlah elemen yang ingin diambil sebagai parameter kedua.

randomPick(members, 2);

Penjelasan

Inti fungsi ini hanya melakukan iterasi pada array sebanyak jumlah elemen yang ingin diambil. Pada setiap iterasi, kode ini akan mengacak angka yang tidak lebih dari jumlah elemen dalam array tersebut. Dimana angka acak itu menjadi indeks untuk memilih elemen pada array.

// anyNumber is number of elements you picked
for (let i = 0; i < anyNumber; i++) {
  // Random number based on source array length
  const magicNumber = Math.floor(Math.random() * (source.length - Math.random()));
}
Kode membuat angka acak ini terinspirasi dari snippet Joshua W. Comeau

Agar elemen yang diambil tidak duplikat, maka elemen yang sudah diambil dikeluarkan menggunakan fungsi splice. Bagian ini juga sekaligus menjadi cara memilih elemen tersebut.

// let result = [];
result.push(source.splice(magicNumber, 1)[0]);

Mungkin kamu berfikir kalau memakai fungsi splice nantinya sumber array akan berubah. Jangan khawatir! Fungsi ini tidak akan memodifikasi array aslinya. Itulah mengapa sebelum melakukan iterasi, sumber array digandakan terlebih dahulu kemudian array baru itulah yang dipakai dan dimodifikasi.

Lalu yang terakhir, terdapat satu variabel untuk mencatat berapa jumlah elemen pada array yang sebelumnya sudah saya sebutkan dipakai pada algoritma pengambilan elemen secar acak.

// Duplicate original array
let poppedArray = [].concat(source);
// Flag to track current length of duplicated source array
let currentLength = poppedArray.length;

Tidak lupa setiap selesai memilih elemen pada array, variabel currentLength ini akan diperbarui karena sumber array telah dipotong (dengan splice).

for (let i = 0; i < anyNumber; i++) {
  ...

  currentLength = poppedArray.length;
}