Ottenere un valore casuale da un array JavaScript


794

Prendere in considerazione:

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

Come posso selezionare un valore casuale da questo array usando JavaScript?

Risposte:


1482

È una semplice linea

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

Esempio

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 questo è corretto. Nota la Math.floor(Math.random(...))chiamata, che completa.
ashes999,

33
Ahh, ho imparato qualcosa di nuovo. Stavo discutendo il caso in cui è ESATTAMENTE 1, ma apparentemente (secondo W3Schools) Math.random è compreso tra 0 compreso e 1 esclusivo. Colpa mia.
SapphireSun

13
Potrei sbagliarmi, ma ricordo di var rand = myArray[Math.random() * myArray.length>>0]essere leggermente più veloce
vrugtehagel il

6
per ogni evenienza, se stai già utilizzando lodash puoi usare _.sample (array)
Gabriel Matusevich,

2
Preferisco questa variante:var rand = myArray[Math.random() * myArray.length | 0]
Nicolas

76

Se hai già un carattere di sottolineatura o lodash incluso nel tuo progetto, puoi usarlo _.sample.

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

Se è necessario ottenere più di un elemento in modo casuale, è possibile passarlo come secondo argomento nel trattino basso:

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

o usa il _.sampleSizemetodo in lodash:

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

Quando si utilizza il dattiloscritto: tenere presente che il tipo restituito sarebbe "stringa | non definito" anziché "stringa" dato un array di stringhe.
Stephan Schielke,

23

Metodo prototipo

Se hai intenzione di ottenere un valore casuale molto, potresti voler definire una funzione per esso.

Innanzitutto, inseriscilo nel tuo codice da qualche parte:

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

Adesso:

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

Codice rilasciato di pubblico dominio ai sensi della licenza CC0 1.0 .


E questo fa cosa?
Ken Sharp,

3
@KenSharp ti consente di chiamare .sample()qualsiasi array per ottenere un oggetto casuale
Ben Aubin

5
È necessario evitare l'estensione dei tipi di oggetti nativi. Ho cancellato la mia risposta, visto che è stata votata molto, ma promuovendo cattive pratiche. Per ulteriori discussioni su questo tema si veda ad esempio stackoverflow.com/questions/14034180/... e eslint.org/docs/rules/no-extend-native
Markus Amalthea Magnuson

20

~~è molto più veloce di Math.Floor(), quindi quando si tratta di ottimizzazione delle prestazioni durante la produzione di output utilizzando elementi dell'interfaccia utente, ~~vince il gioco. ULTERIORI INFORMAZIONI

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

Ma se sai che l'array avrà milioni di elementi di quelli che potresti voler riconsiderare tra Operatore Bitwise e Math.Floor(), poiché l' operatore Bitwise si comporta in modo strano con numeri grandi. Vedi l'esempio seguente spiegato con l'output. ULTERIORI INFORMAZIONI

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

1
Il link è morto, comunque post interessante e lo Math.floor
userò

1
l'uso dell'operatore "bitwise not", sebbene più veloce, non è così leggibile, quindi devi scegliere ciò che è più importante per te
Maciej Urbański,

16

Supponi di voler scegliere un oggetto casuale diverso dall'ultima volta (non proprio casuale, ma comunque un requisito comune) ...

Sulla base della risposta di @Markus, possiamo aggiungere un'altra funzione prototipo:

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

E implementare in questo modo:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)

11

Se hai valori fissi (come un elenco di nomi di mese) e desideri una soluzione a una riga

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

La seconda parte dell'array è un'operazione di accesso come descritto in Perché [5,6,8,7] [1,2] = 8 in JavaScript?


2
Tale codice è una pratica cattiva e dannosa. Non dovrebbe mai essere usato in produzione. Ha una bassa leggibilità e una lunghezza dell'array codificata. La persona che modifica l'input dell'array potrebbe dimenticare di modificare la lunghezza codificata alla fine.
Gabbiano,

@Seagull OP non ha mai richiesto un ambiente specifico. Anche questo commento non ha senso in quanto potrebbe essere applicato a quasi tutte le risposte a questa domanda;)
IG Pascual,

Ma la maggior parte delle persone arriva a questa domanda dalla ricerca di Google e può utilizzare la soluzione in scenari diversi dall'OP originale.
Gabbiano,

Le persone di @Seagull Haha sono libere di decidere quale approccio usare, non sono la faq guida dell'igiene personale!
IG Pascual,

10

La versione più corta:

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

Cosa fa | 0?
Ken Sharp

2
Trasformerà Float su Int, come in Math.floor.
Foxiris,

4
@KenSharp | 0stesso è un'operazione bit a bit che non fa nulla, ma in javascript i float vengono convertiti in ints prima di qualsiasi operazione bit a bit . Quindi è qualcosa di simile a come + ''non fa davvero nulla ma può essere usato per convertire cose in stringhe.
pastore

Non è la stessa cosa, Math.floorma è la cosa giusta da fare qui. È un operatore quindi è più veloce che Math.floorse non altro perché in qualsiasi momento durante l'esecuzione di un codice può fare Math.floor = someOtherFunctione non possono fare lo stesso per '|'. D'altra parte, come per Math.floore |essere diverso provare Math.floor(-1.5)vs -1.5 | 0. A proposito, non hai bisogno delle parentesi. |ha una precedenza molto bassa.
Gman,

7

Se si desidera scriverlo su una riga, come la soluzione di Pascual, un'altra soluzione sarebbe quella di scriverlo utilizzando la funzione di ricerca di ES6 (in base al fatto, che la probabilità di selezionare casualmente uno degli nelementi è 1/n):

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

Utilizzare tale approccio a scopo di test e se esiste una buona ragione per non salvare l'array solo in una variabile separata. Altrimenti le altre risposte ( floor(random()*lengthe usando una funzione separata) sono la tua strada da percorrere.


Soluzione molto originale Ottimo lavoro! A proposito, l'unica vera e dinamica soluzione one-liner qui.
Slavik Meltser

7

Faker.js ha molte funzioni di utilità per la generazione di dati di test casuali. È una buona opzione nel contesto di una suite di test:

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

Come hanno già detto i commentatori, generalmente non dovresti usare questa libreria nel codice di produzione.


8
Per un problema semplice come questo, l'aggiunta di una dipendenza per un'intera libreria non è necessaria e si aggiunge al bloat del codice. Semmai, potresti potenzialmente raccomandare il metodo effettivo da Fakercui selezionare un elemento di array casuale.
Pixxl

1
I "problemi semplici" come questo sono di solito risolti da biblioteche che forniscono una soluzione semplice a un problema che centinaia di persone hanno già dovuto affrontare. Quelle librerie sono generalmente robuste e ben sottoposte a debug e trattano vari avvertimenti che non vogliamo implementare di nuovo. In genere sarebbe la situazione in cui consiglierei di utilizzare una libreria.
smonff,

Quindi dovresti semplicemente copiare quel metodo dalla libreria e inserirlo in un file utils
Rick Bross,

Il consiglio che le biblioteche dovrebbero essere valutate per il peso della pagina WRT costo / beneficio quando vengono spedite a un browser web è un buon consiglio e sono pienamente d'accordo sul fatto che spedire Faker.js a un browser sarebbe ridicolo. Tuttavia, la domanda non menziona quale runtime JS viene utilizzato. Per un runtime basato su NodeJS le dipendenze più pesanti sono perfettamente ragionevoli, come nel caso in cui sto usando Faker.js - nelle suite di test Cucumber JS.
Nathan,

6

La modifica del prototipo di array può essere dannosa. Qui è una semplice funzione per fare il lavoro.

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
}

Uso:

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

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

3

Funzione ricorsiva e autonoma che può restituire un numero qualsiasi di elementi (identico a 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])
}

2

Per ottenere l' uso di array di oggetti casuali criptati

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

Questo è simile, ma più generale, alla soluzione di @Jacob Relkin:

Questo è ES2015:

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

Il codice funziona selezionando un numero casuale compreso tra 0 e la lunghezza dell'array, quindi restituendo l'elemento in quell'indice.


1

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

o versione abbreviata equivalente:

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

Codice di esempio:

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


1

Funzione semplice:

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

O

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

O

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

Sarebbe meglio impostare la variabile myArrayy all'interno della funzione in modo da non inquinare lo spazio dei nomi globale.
Neil Meyer,

0

Secondo me, meglio che scherzare con i prototipi o dichiararlo appena in tempo, preferisco esporlo alla finestra:

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

Ora ovunque nella tua app la chiami come:

var rand = window.choice.call(array)

In questo modo è ancora possibile utilizzare il for(x in array)loop correttamente


1
Non ero qui quando qualcuno lo ha declassato, e non lo ho declassato, ma la mia ipotesi è che esporlo alla finestra stia praticamente dichiarando una variabile globale. Vedi: stackoverflow.com/questions/2613310/…
Chris

1
Non dovresti mai usarlo for...insu array, o in generale. Corri il rischio di camminare sulla catena del prototipo. È anche pensato per tutte le proprietà di un oggetto, non per tutti gli indici in un array. Se si desidera utilizzare un iteratore su un array, utilizzare for (var i = 0; i < foo.length; i++){}. Ancora meglio, usa Array.prototype.forEachinvece qualcosa di simile .
Robert,

1
Non preferisco questo perché inquina l'ambito globale. Si potrebbe dire che questo potrebbe essere l'unico ad essere lì, ma darà le abitudini di violare quella buona pratica.
Jekk,

0

Ho trovato un modo per aggirare le complicazioni della risposta più alta, semplicemente concatenando la variabile rand a un'altra variabile che consente a quel numero di essere visualizzato nella chiamata di myArray [] ;. Eliminando il nuovo array creato e giocando con le sue complicazioni, ho trovato una soluzione funzionante:

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

Sono confuso perché concatmai sta cambiando qui ... di per randomsé non lo sta cambiando, e nient'altro viene chiamato più di una volta ....
BalinKingOfMoria Reinstate CMs

1
Questa soluzione non ha del tutto senso. Perché stai creando una variabile chiamata concat?
superluminario,

0

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

Impostate una variabile costante sull'array, quindi avete un'altra costante che sceglie casualmente tra i tre oggetti dell'array e quindi la funzione restituisce semplicemente i risultati.


-1

Un modo generico per ottenere elementi casuali:

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 rende questo un po 'più semplice e leggibile:

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


1
Solo curioso: perché i downvotes?
Leponzo,

1
alcune persone non sono fan degli acquisti nelle biblioteche per il codice che potrebbero scrivere da sole, anche se renderebbe le cose più veloci e più leggibili. se la libreria non funziona per qualche motivo, il tuo sito Web ora ha un problema tecnico. randojs non va giù, ma non lo sanno perché non è così noto come le librerie come jQuery per esempio
Aaron Plocharczyk,

-2

Ecco un esempio di come farlo:

$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

un altro metodo semplice:

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

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

-3

Crea un valore casuale e passa all'array

Si prega di provare il seguente codice ..

//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
Questa risposta utilizza la stessa soluzione della risposta già accettata. Dovresti astenersi dall'aggiungere la stessa soluzione due volte e invece far apparire solo altre possibili alternative che potrebbero contribuire maggiormente alla conversazione.
Pixxl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.