Mendapatkan nilai acak dari array JavaScript

794

Mempertimbangkan:

var myArray = ['January', 'February', 'March'];    

Bagaimana saya bisa memilih nilai acak dari array ini menggunakan JavaScript?

Sarah
sumber

Jawaban:

1482

Ini adalah one-liner sederhana

const randomElement = array[Math.floor(Math.random() * array.length)];

Contoh

const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const randomMonth = months[Math.floor(Math.random() * months.length)];

console.log("random month =>", randomMonth);

Jacob Relkin
sumber
9
@ Safhireun, ini benar. Perhatikan Math.floor(Math.random(...))panggilan, yang dibulatkan ke bawah.
ashes999
33
Ahh, saya sudah belajar sesuatu yang baru. Saya sedang membahas kasus di mana itu sama PERSIS 1, tetapi ternyata (menurut W3Schools) Math.random adalah antara 0 inklusif dan 1 eksklusif. Salahku.
SapphireSun
13
Saya mungkin salah, tetapi saya ingat var rand = myArray[Math.random() * myArray.length>>0]sedikit lebih cepat
vrugtehagel
6
untuk jaga-jaga, jika Anda sudah menggunakan lodash Anda dapat menggunakan _.sample (array)
Gabriel Matusevich
2
Saya lebih suka varian ini:var rand = myArray[Math.random() * myArray.length | 0]
Nicolas
76

Jika Anda sudah mendapat garis bawah atau tanda lahir yang termasuk dalam proyek Anda, Anda dapat menggunakannya _.sample.

// will return one item randomly from the array
_.sample(['January', 'February', 'March']);

Jika Anda perlu mendapatkan lebih dari satu item secara acak, Anda dapat meneruskannya sebagai argumen kedua dalam garis bawah:

// will return two items randomly from the array using underscore
_.sample(['January', 'February', 'March'], 2);

atau gunakan _.sampleSizemetode ini di lodash:

// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);
Brendan Nee
sumber
Saat menggunakan naskah: Perlu diketahui bahwa jenis kembali akan menjadi "string | undefined", bukan "string" diberi array string.
Stephan Schielke
23

Metode Prototipe

Jika Anda berencana untuk mendapatkan nilai acak banyak, Anda mungkin ingin mendefinisikan fungsi untuk itu.

Pertama, letakkan ini di kode Anda di suatu tempat:

Array.prototype.sample = function(){
  return this[Math.floor(Math.random()*this.length)];
}

Sekarang:

[1,2,3,4].sample() //=> a random element

Kode dirilis ke domain publik di bawah ketentuan lisensi CC0 1.0 .

Ben Aubin
sumber
Dan ini melakukan apa?
Ken Sharp
3
@ KenSharp memungkinkan Anda untuk memanggil .sample()array apa pun untuk mendapatkan item acak
Ben Aubin
5
Memperluas jenis objek asli harus dihindari. Saya telah menghapus jawaban saya, melihat itu banyak dipilih, tetapi mempromosikan praktik buruk. Untuk diskusi lebih lanjut tentang masalah ini, lihat misalnya stackoverflow.com/questions/14034180/… dan eslint.org/docs/rules/no-extend-native
Markus Amalthea Magnuson
20

~~jauh lebih cepat daripada Math.Floor(), jadi ketika datang ke optimasi kinerja sambil menghasilkan output menggunakan elemen UI, ~~memenangkan permainan. INFO LEBIH LANJUT

var rand = myArray[~~(Math.random() * myArray.length)];

Tetapi jika Anda tahu bahwa array akan memiliki jutaan elemen daripada Anda mungkin ingin mempertimbangkan kembali antara Operator Bitwise dan Math.Floor(), sebagai operator bitwise berperilaku aneh dengan jumlah besar. Lihat contoh di bawah ini dijelaskan dengan output. INFO LEBIH LANJUT

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343
Ankur Soni
sumber
1
Tautan sudah mati, betapapun posnya menarik dan saya akan menggunakan ini lebih dari Math.floorsekarang :)
aabbccsmith
1
menggunakan operator "bitwise not", sementara lebih cepat, tidak dapat dibaca, jadi Anda harus memilih apa yang lebih penting bagi Anda
Maciej Urbański
16

Katakanlah Anda ingin memilih item acak yang berbeda dari yang terakhir kali (tidak benar-benar acak, tetapi masih merupakan persyaratan umum) ...

Membangun berdasarkan jawaban oleh @ Markus, kita dapat menambahkan fungsi prototipe lain:

Array.prototype.randomDiffElement = function(last) {
   if (this.length == 0) {
      return;
   } else if (this.length == 1) {
      return this[0];
   } else {
      var num = 0;
      do {
         num = Math.floor(Math.random() * this.length);
      } while (this[num] == last);
      return this[num];
   }
}

Dan implementasikan seperti ini:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)
CrazyTim
sumber
11

Jika Anda memiliki nilai tetap (seperti daftar nama bulan) dan ingin solusi satu baris

var result = ['January', 'February', 'March'][Math.floor(Math.random() * 3)]

Bagian kedua dari array adalah operasi akses seperti yang dijelaskan dalam Mengapa [5,6,8,7] [1,2] = 8 dalam JavaScript?

IG Pascual
sumber
2
Kode semacam itu adalah praktik yang buruk dan berbahaya. Seharusnya tidak pernah digunakan dalam produksi. Ini memiliki keterbacaan yang rendah dan memiliki panjang array hardcoded. Orang yang mengubah input array mungkin lupa mengedit panjang yang dikodekan pada akhirnya.
Seagull
@ Seagull OP tidak pernah meminta lingkungan tertentu. Juga komentar ini tidak ada artinya karena dapat diterapkan ke hampir semua jawaban dalam pertanyaan ini;)
IG Pascual
Tetapi kebanyakan orang sampai pada pertanyaan ini dari pencarian Google dan mungkin menggunakan solusi dalam skenario lain daripada OP asli.
Seagull
@ Seagull Haha orang bebas memutuskan pendekatan mana yang akan digunakan, saya bukan faq pedoman kode bersih!
IG Pascual
10

Versi terpendek:

var myArray = ['January', 'February', 'March']; 
var rand = myArray[(Math.random() * myArray.length) | 0]
foxiris
sumber
Apa yang | 0harus dilakukan
Ken Sharp
2
Ini akan mengubah Float ke Int, sama seperti Math.floor.
foxiris
4
@ KenSharp | 0sendiri adalah operasi bitwise yang tidak melakukan apa-apa, tetapi dalam float javascript dikonversi ke ints sebelum operasi bitwise . Jadi itu seperti bagaimana + ''tidak benar-benar melakukan apa pun tetapi dapat digunakan untuk mengubah hal menjadi string.
dshepherd
Ini tidak sama dengan Math.floortetapi itu adalah hal yang benar untuk dilakukan di sini. Ini adalah operator sehingga lebih cepat daripada Math.floorjika hanya karena sewaktu-waktu menjalankan beberapa kode dapat dilakukan Math.floor = someOtherFunctiondan mereka tidak dapat melakukan hal yang sama untuk '|'. Di sisi lain seperti untuk Math.floordan |menjadi berbeda mencoba Math.floor(-1.5)vs -1.5 | 0. Ngomong-ngomong, kamu tidak membutuhkan tanda kurung. |memiliki prioritas yang sangat rendah.
gman
7

Jika Anda ingin menulisnya pada satu baris, seperti solusi Pascual, solusi lain adalah menuliskannya menggunakan fungsi find ES6 (berdasarkan pada fakta, bahwa kemungkinan memilih secara acak salah satu nitem adalah 1/n):

var item = ['A', 'B', 'C', 'D'].find((_, i, ar) => Math.random() < 1 / (ar.length - i));
console.log(item);

Gunakan pendekatan itu untuk tujuan pengujian dan jika ada alasan bagus untuk tidak menyimpan array dalam variabel terpisah saja. Kalau tidak, jawaban lain ( floor(random()*lengthdan menggunakan fungsi terpisah) adalah jalan Anda.

Stephan
sumber
Solusi yang sangat asli. Kerja bagus! Omong-omong, satu-satunya solusi satu-liner yang nyata dan dinamis di sini.
Slavik Meltser
7

Faker.js memiliki banyak fungsi utilitas untuk menghasilkan data uji acak. Ini adalah opsi yang baik dalam konteks test suite:

const Faker = require('faker');
Faker.random.arrayElement(['January', 'February', 'March']);

Seperti yang disebutkan oleh komentator, Anda biasanya tidak boleh menggunakan perpustakaan ini dalam kode produksi.

Nathan
sumber
8
Untuk masalah sederhana seperti ini, menambahkan ketergantungan untuk seluruh perpustakaan tidak perlu dan menambah kode mengasapi. Jika ada, Anda berpotensi merekomendasikan metode aktual Fakeryang memilih elemen array acak.
Pixxl
1
"Masalah sederhana" seperti ini biasanya diselesaikan oleh perpustakaan yang memberikan solusi sederhana untuk masalah yang sudah dihadapi ratusan orang. Perpustakaan-perpustakaan itu biasanya kuat dan memiliki banyak debug serta berurusan dengan berbagai peringatan yang tidak ingin kami terapkan kembali. Biasanya situasi di mana saya akan merekomendasikan untuk menggunakan perpustakaan.
smonff
Daripada Anda hanya perlu menyalin satu metode dari perpustakaan dan meletakkannya di file utils
Rick Bross
Saran bahwa perpustakaan harus dinilai untuk biaya / manfaat, berat halaman WRT ketika dikirim ke peramban web adalah saran yang bagus dan saya sepenuh hati setuju bahwa pengiriman Faker.js ke peramban akan menjadi konyol. Namun, pertanyaannya tidak menyebutkan runtime JS mana yang sedang digunakan. Untuk runtime berbasis NodeJS, dependensi yang lebih berat sangat masuk akal yang merupakan kasus di mana saya menggunakan Faker.js - dalam suite uji Cucumber JS.
Nathan
6

Mengedit prototipe Array bisa berbahaya. Ini dia fungsi sederhana untuk melakukan pekerjaan itu.

function getArrayRandomElement (arr) {
  if (arr && arr.length) {
    return arr[Math.floor(Math.random() * arr.length)];
  }
  // The undefined will be returned if the empty array was passed
}

Pemakaian:

// Example 1
var item = getArrayRandomElement(['January', 'February', 'March']);

// Example 2
var myArray = ['January', 'February', 'March'];
var item = getArrayRandomElement(myArray);
Camar
sumber
3

Fungsi rekursif, mandiri yang dapat mengembalikan sejumlah item (identik dengan lodash.sampleSize ):

function getRandomElementsFromArray(array, numberOfRandomElementsToExtract = 1) {
    const elements = [];

    function getRandomElement(arr) {
        if (elements.length < numberOfRandomElementsToExtract) {
            const index = Math.floor(Math.random() * arr.length)
            const element = arr.splice(index, 1)[0];

            elements.push(element)

            return getRandomElement(arr)
        } else {
            return elements
        }
    }

    return getRandomElement([...array])
}
menyusut
sumber
2

Untuk mendapatkan penggunaan array item acak crypto-strong

let rndItem = a=> a[rnd()*a.length|0];
let rnd = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;

var myArray = ['January', 'February', 'March'];

console.log( rndItem(myArray) )

Kamil Kiełczewski
sumber
1

Ini mirip dengan, tetapi lebih umum daripada, solusi @ Jacob Relkin:

Ini ES2015:

const randomChoice = arr => {
    const randIndex = Math.floor(Math.random() * arr.length);
    return arr[randIndex];
};

Kode berfungsi dengan memilih angka acak antara 0 dan panjang array, lalu mengembalikan item pada indeks itu.

Max Heiber
sumber
1

var item = myArray[Math.floor(Math.random()*myArray.length)];

atau versi yang lebih pendek yang setara:

var item = myArray[(Math.random()*myArray.length)|0];

Kode sampel:

var myArray = ['January', 'February', 'March'];    
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);

Pavel P
sumber
1

Fungsi sederhana:

var myArray = ['January', 'February', 'March'];
function random(array) {
     return array[Math.floor(Math.random() * array.length)]
}
random(myArray);

ATAU

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

ATAU

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
Dhakshith
sumber
Akan lebih baik untuk mengatur variabel myArrayy di dalam fungsi Anda agar tidak mencemari namespace global.
Neil Meyer
0

Menurut pendapat saya, lebih baik daripada bermain-main dengan prototipe, atau mendeklarasikannya tepat waktu, saya lebih suka mengeksposnya ke jendela:

window.choice = function() {
  if (!this.length || this.length == 0) return;
  if (this.length == 1) return this[0];
  return this[Math.floor(Math.random()*this.length)];
}

Sekarang di mana saja di aplikasi Anda Anda menyebutnya seperti:

var rand = window.choice.call(array)

Dengan cara ini Anda masih bisa menggunakan for(x in array)loop dengan benar

frankies
sumber
1
Saya tidak ada di sini ketika ada orang yang menurunkannya, dan saya tidak menghapusnya, tetapi dugaan saya adalah bahwa mengeksposnya ke jendela pada dasarnya mendeklarasikan variabel global. Lihat: stackoverflow.com/questions/2613310/…
Chris
1
Anda seharusnya tidak pernah menggunakan for...inarray, atau bahkan secara umum. Anda berisiko berjalan di rantai prototipe. Ini juga dimaksudkan untuk semua properti objek, tidak semua indeks dalam array. Jika Anda ingin menggunakan iterator pada array, gunakan for (var i = 0; i < foo.length; i++){}. Lebih baik lagi, gunakan sesuatu seperti itu Array.prototype.forEach.
Robert
1
Saya tidak suka ini karena mencemari ruang lingkup global. Bisa dibilang ini mungkin satu-satunya yang ada di sana, tetapi itu akan memberi kebiasaan melanggar praktik yang baik itu.
Jekk
0

Saya telah menemukan cara mengatasi komplikasi jawaban teratas, hanya dengan menggabungkan rand variabel ke variabel lain yang memungkinkan angka tersebut ditampilkan di dalam pemanggilan myArray [] ;. Dengan menghapus array baru yang dibuat dan mempermainkan komplikasinya, saya telah menghasilkan solusi yang berfungsi:

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>

var myArray = ['January', 'February', 'March', 'April', 'May'];    

var rand = Math.floor(Math.random() * myArray.length);

var concat = myArray[rand];

function random() {
   document.getElementById("demo").innerHTML = (concat);
}
</script>

<button onClick="random();">
Working Random Array generator
</button>

</body>
</html>
FaverosGema
sumber
Saya bingung mengapa concatselalu berubah di sini ... randomitu sendiri tidak mengubahnya, dan tidak ada yang dipanggil lebih dari sekali ....
BalinKingOfMoria Reinstate CMs
1
Solusi ini tidak sepenuhnya masuk akal. Mengapa Anda membuat variabel yang disebut concat?
superluminary
0

static generateMonth() { 
const theDate = ['January', 'February', 'March']; 
const randomNumber = Math.floor(Math.random()*3);
return theDate[randomNumber];
};

Anda menetapkan variabel konstan ke array, Anda kemudian memiliki konstanta lain yang memilih secara acak antara tiga objek dalam array dan kemudian fungsinya mengembalikan hasil.

Neil Meyer
sumber
-1

Cara umum untuk mendapatkan elemen acak:

let some_array = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
let months = random_elems(some_array, 3);

console.log(months);

function random_elems(arr, count) {
  let len = arr.length;
  let lookup = {};
  let tmp = [];

  if (count > len)
    count = len;

  for (let i = 0; i < count; i++) {
    let index;
    do {
      index = ~~(Math.random() * len);
    } while (index in lookup);
    lookup[index] = null;
    tmp.push(arr[index]);
  }

  return tmp;
}

Rafael
sumber
-1

randojs membuat ini sedikit lebih sederhana dan mudah dibaca:

console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>

Aaron Plocharczyk
sumber
1
Hanya ingin tahu: mengapa downvotes?
Leponzo
1
beberapa orang bukan penggemar sumber di perpustakaan untuk kode yang dapat mereka tulis sendiri, bahkan jika itu akan membuat segalanya lebih cepat dan lebih mudah dibaca. jika perpustakaan turun karena suatu alasan, situs web Anda sekarang memiliki masalah. randojs tidak turun, tetapi mereka tidak tahu itu karena itu tidak dikenal seperti perpustakaan seperti jQuery misalnya
Aaron Plocharczyk
-2

Berikut adalah contoh cara melakukannya:

$scope.ctx.skills = data.result.skills;
    $scope.praiseTextArray = [
    "Hooray",
    "You\'re ready to move to a new skill", 
    "Yahoo! You completed a problem", 
    "You\'re doing great",  
    "You succeeded", 
    "That was a brave effort trying new problems", 
    "Your brain was working hard",
    "All your hard work is paying off",
    "Very nice job!, Let\'s see what you can do next",
    "Well done",
    "That was excellent work",
    "Awesome job",
    "You must feel good about doing such a great job",
    "Right on",
    "Great thinking",
    "Wonderful work",
    "You were right on top of that one",
    "Beautiful job",
    "Way to go",
    "Sensational effort"
  ];

  $scope.praiseTextWord = $scope.praiseTextArray[Math.floor(Math.random()*$scope.praiseTextArray.length)];
varun
sumber
-2

metode lain yang mudah:

var myArray = ['keke','keko','cano','halo','zirto'];

var randomValue = myArray[Math.round((Math.random()*1000))%myArray.length];
Kamuran Sönecek
sumber
-3

Buat satu nilai acak dan berikan ke array

Silakan coba kode berikut ..

//For Search textbox random value
var myPlaceHolderArray = ['Hotels in New York...', 'Hotels in San Francisco...', 'Hotels Near Disney World...', 'Hotels in Atlanta...'];
var rand = Math.floor(Math.random() * myPlaceHolderArray.length);
var Placeholdervalue = myPlaceHolderArray[rand];

alert(Placeholdervalue);
Jignesh Darji
sumber
5
Jawaban ini menggunakan solusi yang sama dengan jawaban yang sudah diterima. Anda harus menahan diri untuk tidak menambahkan solusi yang sama dua kali dan alih-alih hanya memunculkan kemungkinan alternatif lain yang akan lebih berkontribusi pada percakapan.
Pixxl