Bir JavaScript dizisinden rastgele bir değer elde etme


794

Düşünmek:

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

JavaScript kullanarak bu diziden rastgele bir değeri nasıl seçebilirim?

Yanıtlar:


1481

Basit bir astardır

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

Misal

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);


9
@SapphireSun bu doğru. Yuvarlanan Math.floor(Math.random(...))çağrıyı not edin .
19es14

33
Ahh, yeni bir şey öğrendim. TAM 1'e eşit olduğu durumu tartışıyordum, ama görünüşe göre (W3Schools'a göre) Math.random 0 dahil ve 1 özel arasında. Benim hatam.
SapphireSun

13
Yanılıyor olabilirim ama var rand = myArray[Math.random() * myArray.length>>0]biraz daha hızlı olduğumu hatırlıyorum
vrugtehagel

6
Her ihtimale karşı, zaten lodash kullanıyorsanız _.sample (dizi)
Gabriel Matusevich'i kullanabilirsiniz

2
Bu varyantı tercih ediyorum:var rand = myArray[Math.random() * myArray.length | 0]
Nicolas

76

Projenize zaten alt çizginiz veya kötü işaretiniz varsa kullanabilirsiniz _.sample.

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

Birden fazla öğeyi rastgele almanız gerekiyorsa, bunu alt çizgide ikinci bir argüman olarak iletebilirsiniz:

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

veya _.sampleSizeyöntemi lodash'da kullanın :

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

Typescript kullanırken: Bir string dizisi verildiğinde "string" yerine dönüş tipinin "string | undefined" olacağını unutmayın.
Stephan Schielke

23

Prototip Yöntemi

Rastgele bir değer almayı planlıyorsanız, bunun için bir işlev tanımlamak isteyebilirsiniz.

İlk olarak, kodunuza bir yere koyun:

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

Şimdi:

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

CC0 1.0 lisansı koşulları altında kamu malı olarak yayınlanan kod .


Ve bu ne yapar?
Ken Sharp

3
@KenSharp .sample()rastgele bir öğe almak için herhangi bir diziyi aramak için izin verir
Ben Aubin

5
Yerel nesne türlerinin genişletilmesinden kaçınılmalıdır. Cevabımı sildim, çok fazla değerlendirildiğini gördüm, ancak kötü uygulamayı teşvik ettim. Bu konuda daha fazla tartışma için örneğin bkz stackoverflow.com/questions/14034180/... ve eslint.org/docs/rules/no-extend-native
Markus Amelteya Magnuson

20

~~daha hızlıdır Math.Floor()UI öğeleri kullanarak çıktıyı üreten ederken performans optimizasyonu için geldiğinde bu yüzden, ~~oyunu kazanır. DAHA FAZLA BİLGİ

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

Ancak, dizinin Bitwise Operator ile yeniden düşünmek isteyebileceğinizden milyonlarca elemente sahip olacağını biliyorsanız, Math.Floor()bitwise operatör büyük sayılarla garip davranır. Çıktı ile açıklanan aşağıdaki örneğe bakın. DAHA FAZLA BİLGİ

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343

1
Bağlantı öldü, ancak ilginç yazı ve bunu Math.floorşimdi daha fazla
kullanacağım

"bitwise not" operatörünü kullanmak daha hızlı olsa da okunabilir değil, bu yüzden sizin için daha önemli olanı seçmelisiniz
Maciej Urbański

16

Son zamandan farklı rastgele bir öğe seçmek istediğinizi varsayalım (gerçekten rastgele değil, ancak ortak bir gereksinim) ...

@ Markus'un cevabına dayanarak, başka bir prototip işlevi ekleyebiliriz:

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];
   }
}

Ve şöyle uygulayın:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)

11

Sabit değerleriniz varsa (ay adı listesi gibi) ve tek satırlık bir çözüm istiyorsanız

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

Dizinin ikinci kısmı, JavaScript'te neden [5,6,8,7] [1,2] = 8?


2
Böyle bir kod kötü ve zararlı bir uygulamadır. Asla üretimde kullanılmamalıdır. Okunabilirliği düşüktür ve sabit kodlanmış bir dizi uzunluğuna sahiptir. Dizi girişini değiştiren kişi, sonunda kodlanmış uzunluğu düzenlemeyi unutabilir.
Martı

@Seagull OP hiçbir zaman belirli bir ortam istemedi. Ayrıca bu yorum, bu sorudaki hemen hemen tüm cevaplara uygulanabileceği için anlamsızdır;)
IG Pascual

Ancak çoğu kişi bu soruya Google aramadan gelir ve çözümü orijinal OP dışındaki diğer senaryolarda kullanabilir.
Martı

@Seagull Haha insanlar hangi yaklaşımı kullanacaklarına karar vermekte özgürler, temiz kod guideliness faq değilim!
IG Pascual

10

En kısa sürüm:

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

Ne yapar | 0?
Ken Sharp

2
Float'ı Math.floor ile aynı Int'ye çevirir.
foxiris

4
@KenSharp | 0kendisi hiçbir şey yapmaz bitsel bir işlemdir, ancak javascript şamandıralar herhangi bir bitsel işlemden önce ints dönüştürülür . Yani bu + ''gerçekten hiçbir şey yapmayan bir şeydir ama işleri dizelere dönüştürmek için kullanılabilir.
dshepherd

Aynı değil Math.floorama burada yapılacak doğru şey bu. Bu bir operatördür, Math.floorçünkü sadece kod çalışırken herhangi bir zamanda yapabileceği Math.floor = someOtherFunctionve '|' için aynısını yapamayacaklarından daha hızlıdır . Öte yandan olduğu gibi Math.floorve |farklı olmak Math.floor(-1.5)vs deneyin -1.5 | 0. Bu arada parantezlere ihtiyacınız yok. |çok düşük bir önceliğe sahiptir.
gman

7

Pascual'ın çözümü gibi bir satıra yazmak istiyorsanız, başka bir çözüm ES6'nın find işlevini kullanarak yazmak olacaktır ( nöğelerden birini rastgele seçme olasılığının olduğu gerçeğine dayanarak 1/n):

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

Bu yaklaşımı test amacıyla ve diziyi yalnızca ayrı bir değişkene kaydetmemek için iyi bir neden varsa kullanın. Aksi takdirde, diğer yanıtlar ( floor(random()*lengthve ayrı bir işlev kullanarak) yolunuzdur.


Çok özgün bir çözüm. İyi iş! Bu arada, burada tek gerçek ve dinamik tek katmanlı çözüm.
Slavik Meltser

7

Faker.js , rastgele test verileri oluşturmak için birçok yardımcı fonksiyona sahiptir. Test paketi bağlamında iyi bir seçenektir:

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

Yorum yapanların belirttiği gibi, genellikle bu kütüphaneyi üretim kodunda kullanmamalısınız.


8
Bunun gibi basit bir sorun için, tüm kütüphaneye bağımlılık eklemek gereksizdir ve kod şişmesine eklenir. Herhangi bir şey varsa, Fakerrastgele bir dizi öğesi seçen gerçek yöntemi önerebilirsiniz .
Pixxl

1
Bunun gibi "basit problem" genellikle yüzlerce kişinin karşılaştığı bir soruna basit bir çözüm sağlayan kütüphaneler tarafından çözülür. Bu kütüphaneler genellikle sağlam ve iyi hata ayıklanır ve yeniden uygulamak istemediğimiz çeşitli uyarılarla ilgilenir. Genellikle bir kütüphane kullanmanızı tavsiye edeceğim durumdur.
7'de 001

Daha sonra bu yöntemi kütüphaneden kopyalayıp bir utils dosyasına koymalısınız
Rick Bross

Bir web tarayıcısına gönderildiklerinde kütüphanelerin maliyet / fayda WRT sayfa ağırlığı için değerlendirilmesi gerektiği tavsiyesi sağlam bir tavsiyedir ve Faker.js'nin bir tarayıcıya gönderilmesinin saçma olacağına yürekten katılıyorum. Ancak, soru hangi JS çalışma zamanının kullanıldığından bahsetmez. NodeJS tabanlı bir çalışma zamanı için daha ağır bağımlılıklar, Cucumber JS test paketlerinde Faker.js'yi kullandığım durum için mükemmel derecede makul.
Nathan

6

Dizi prototipini düzenlemek zararlı olabilir. Burada işi yapmak basit bir işlevdir.

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
}

Kullanımı:

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

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

3

İstenen sayıda öğeyi döndürebilen özyinelemeli, bağımsız işlev ( lodash.sampleSize ile aynıdır ):

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])
}

2

Almak için güçlü bir şifrelemeye rasgele öğe form dizi kullanımı

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) )


1

Bu @Jacob Relkin'in çözümüne benzer, ancak daha geneldir:

Bu ES2015:

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

Kod, 0 ile dizinin uzunluğu arasında rasgele bir sayı seçip öğeyi bu dizine döndürerek çalışır.


1

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

veya eşdeğer kısa versiyon:

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

Basit kod:

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


1

Basit İşlev:

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

VEYA

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

VEYA

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

Genel ad alanını kirletmeyecek şekilde myArrayy değişkenini işlevinizde ayarlamak daha iyi olur.
Neil Meyer

0

Bence, prototiplerle uğraşmaktan ya da tam zamanında ilan etmekten daha iyi, pencereye açmayı tercih ederim:

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)];
}

Şimdi uygulamanızın herhangi bir yerine şöyle diyorsunuz:

var rand = window.choice.call(array)

Bu şekilde for(x in array)döngüyü yine de düzgün şekilde kullanabilirsiniz


1
Kimse onu aşağı indirdiğinde ben burada değildim, ve ben aşağıya vurmadım, ama benim tahminim, onu pencereye maruz bırakmanın temelde küresel bir değişken olduğunu bildirmesi. Bakınız: stackoverflow.com/questions/2613310/…
Chris

1
Hiç kullanmamalısınız for...indiziler üzerinde, hatta genel olarak. Prototip zincirini yürüme riski vardır. Ayrıca, bir dizideki tüm dizinler için değil, bir nesnenin tüm özellikleri için tasarlanmıştır. Bir dizide yineleyici kullanmak istiyorsanız, kullanın for (var i = 0; i < foo.length; i++){}. Daha da iyisi, Array.prototype.forEachbunun gibi bir şey kullanın.
Robert

1
Bunu tercih etmiyorum çünkü küresel kapsamı kirletiyor. Bunun sadece orada olabileceğini söyleyebilirsiniz, ancak bu iyi uygulamayı ihlal etme alışkanlığı verecektir.
Jekk

0

Ben sadece bu sayının myArray []; çağrısında görüntülenmesini sağlayan başka bir değişkene birleştirerek üst yanıtın komplikasyonları etrafında bir yol buldum. Oluşturulan yeni diziyi silerek ve komplikasyonları ile oynayarak, çalışan bir çözüm buldum:

<!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>

Neden concatburada hiç değiştiğini karıştı ... randomkendisi onu değiştirmiyor ve başka bir şey birden fazla kez
çağrılıyor

1
Bu çözüm tamamen mantıklı değil. Neden concat adlı bir değişken oluşturuyorsunuz?
superluminary

0

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

Diziye sabit bir değişken ayarlarsınız, daha sonra dizideki üç nesne arasında rasgele seçilen başka bir sabitiniz olur ve işlev basitçe sonuçları döndürür.


-1

Rastgele eleman (lar) almanın genel bir yolu:

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;
}


-1

randojs bunu biraz daha basit ve okunabilir hale getiriyor:

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


1
Sadece merak ediyorum: neden inişler yaptı?
Leponzo

1
bazı insanlar, daha hızlı ve daha okunabilir hale getirseler bile, kendileri yazabilecekleri kodlar için kütüphanelerde kaynak bulma hayranı değildir. kütüphane herhangi bir nedenle çökerse, web sitenizde artık bir aksaklık var. randojs aşağı gitmiyor, ama bilmiyorlar çünkü jQuery gibi kütüphaneler kadar iyi bilinmemektedir
Aaron Plocharczyk

-2

İşte nasıl yapılacağına dair bir örnek:

$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)];

-2

başka bir kolay yöntem:

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

var randomValue = myArray[Math.round((Math.random()*1000))%myArray.length];

-3

Bir rastgele değer oluşturun ve diziye geçin

Lütfen kodu takip etmeyi deneyin ..

//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);

5
Bu cevap, önceden kabul edilmiş cevapla aynı çözümü kullanır. Aynı çözümü iki kez eklemekten kaçınmalı ve bunun yerine sadece konuşmaya daha fazla katkıda bulunabilecek diğer alternatifleri getirmelisiniz.
Pixxl
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.