Obtention d'une valeur aléatoire à partir d'un tableau JavaScript

794

Considérer:

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

Comment puis-je sélectionner une valeur aléatoire dans ce tableau en utilisant JavaScript?

Sarah
la source

Réponses:

1482

C'est un simple doublure

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

Exemple

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
la source
9
@SapphireSun c'est correct. Notez l' Math.floor(Math.random(...))appel, qui arrondit.
ashes999
33
Ahh, j'ai appris quelque chose de nouveau. Je discutais le cas où il est exactement EXACTEMENT 1, mais apparemment (selon W3Schools) Math.random est compris entre 0 inclus et 1 exclusif. Ma faute.
SapphireSun
13
Je me trompe peut-être, mais je me souviens d' var rand = myArray[Math.random() * myArray.length>>0]avoir été un peu plus rapide
vrugtehagel
6
juste au cas où, si vous utilisez déjà lodash, vous pouvez utiliser _.sample (array)
Gabriel Matusevich
2
Je préfère cette variante:var rand = myArray[Math.random() * myArray.length | 0]
Nicolas
76

Si vous avez déjà inclus un trait de soulignement ou un lodash dans votre projet, vous pouvez l'utiliser _.sample.

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

Si vous devez obtenir plus d'un élément au hasard, vous pouvez le passer comme deuxième argument en soulignement:

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

ou utilisez la _.sampleSizeméthode en lodash:

// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);
Brendan Nee
la source
Lorsque vous utilisez tapuscrit: sachez que le type de retour serait "chaîne | non défini" au lieu de "chaîne" étant donné un tableau de chaînes.
Stephan Schielke
23

Méthode prototype

Si vous prévoyez d'obtenir une valeur aléatoire beaucoup, vous voudrez peut-être définir une fonction pour elle.

Tout d'abord, mettez ceci dans votre code quelque part:

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

Maintenant:

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

Code publié dans le domaine public sous les termes de la licence CC0 1.0 .

Ben Aubin
la source
Et cela fait quoi?
Ken Sharp
3
@KenSharp, il vous permet d'appeler .sample()sur n'importe quel tableau pour obtenir un élément aléatoire
Ben Aubin
6
L'extension des types d'objets natifs doit être évitée. J'ai supprimé ma réponse, car elle a été beaucoup votée, mais en encourageant les mauvaises pratiques. Pour plus de discussion sur ce problème, voir par exemple stackoverflow.com/questions/14034180/… et eslint.org/docs/rules/no-extend-native
Markus Amalthea Magnuson
20

~~est beaucoup plus rapide que Math.Floor(), donc quand il s'agit d'optimiser les performances tout en produisant une sortie en utilisant des éléments d'interface utilisateur, ~~gagne la partie. PLUS D'INFORMATIONS

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

Mais si vous savez que le tableau va avoir des millions d'éléments que vous voudrez peut-être reconsidérer entre l'opérateur au niveau du bit et Math.Floor(), en tant qu'opérateur au niveau du bit, se comporter bizarrement avec de grands nombres. Voir l'exemple ci-dessous expliqué avec la sortie. PLUS D'INFORMATIONS

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343
Ankur Soni
la source
1
Le lien est mort, mais le post est intéressant et je l'utiliserai plus que Math.floormaintenant :)
aabbccsmith
1
utiliser l'opérateur "bit à bit non", bien que plus rapide, n'est pas très lisible, vous devez donc choisir ce qui est le plus important pour vous
Maciej Urbański
16

Disons que vous voulez choisir un élément aléatoire différent de la dernière fois (pas vraiment aléatoire, mais toujours une exigence courante) ...

En s'appuyant sur la réponse de @Markus, nous pouvons ajouter une autre fonction prototype:

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

Et implémentez comme ceci:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)
CrazyTim
la source
11

Si vous avez des valeurs fixes (comme une liste de noms de mois) et que vous souhaitez une solution sur une seule ligne

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

La deuxième partie du tableau est une opération d'accès telle que décrite dans Pourquoi [5,6,8,7] [1,2] = 8 en JavaScript?

IG Pascual
la source
2
Un tel code est une pratique mauvaise et nuisible. Il ne doit jamais être utilisé en production. Il a une faible lisibilité et une longueur de tableau codée en dur. La personne qui modifie l'entrée du tableau peut oublier de modifier la longueur codée en dur à la fin.
Seagull
@Seagull OP n'a jamais demandé un environnement spécifique. De plus, ce commentaire n'a pas de sens car il pourrait être appliqué à presque toutes les réponses à cette question;)
IG Pascual
Mais la plupart des gens arrivent à cette question à partir de la recherche Google et peuvent utiliser la solution dans d'autres scénarios que l'OP d'origine.
Seagull
Les gens de @Seagull Haha sont libres de décider de l'approche à utiliser, je ne suis pas la faq du code propre!
IG Pascual du
10

La version la plus courte:

var myArray = ['January', 'February', 'March']; 
var rand = myArray[(Math.random() * myArray.length) | 0]
foxiris
la source
Que fait | 0-il?
Ken Sharp
2
Il passera Float à Int, comme Math.floor.
foxiris
4
@KenSharp | 0lui-même est une opération au niveau du bit qui ne fait rien, mais en javascript, les flottants sont convertis en ints avant toute opération au niveau du bit . C'est donc quelque chose comme comment + ''ne fait vraiment rien mais peut être utilisé pour convertir des choses en chaînes.
dshepherd
Ce n'est pas la même chose Math.floormais c'est la bonne chose à faire ici. C'est un opérateur, donc c'est plus rapide que Math.floorsi seulement parce qu'à tout moment pendant l'exécution, du code peut faire Math.floor = someOtherFunctionet ils ne peuvent pas faire la même chose pour '|'. D'autre part , comme pour Math.flooret |être différent essayer Math.floor(-1.5)vs -1.5 | 0. Soit dit en passant, vous n'avez pas besoin des parenthèses. |a une très faible priorité.
gman
7

Si vous voulez l'écrire sur une ligne, comme la solution de Pascual, une autre solution serait de l'écrire en utilisant la fonction de recherche d'ES6 (basée sur le fait que la probabilité de sélectionner au hasard un des néléments est 1/n):

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

Utilisez cette approche à des fins de test et s'il existe une bonne raison de ne pas enregistrer le tableau dans une variable distincte uniquement. Sinon, les autres réponses ( floor(random()*lengthet en utilisant une fonction séparée) sont votre voie à suivre.

Stephan
la source
Solution très originale. Bon travail! Soit dit en passant, la seule solution monoplace réelle et dynamique ici.
Slavik Meltser
7

Faker.js possède de nombreuses fonctions utilitaires pour générer des données de test aléatoires. C'est une bonne option dans le cadre d'une suite de tests:

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

Comme les commentateurs l'ont mentionné, vous ne devez généralement pas utiliser cette bibliothèque dans le code de production.

Nathan
la source
8
Pour un problème simple comme celui-ci, l'ajout d'une dépendance pour une bibliothèque entière n'est pas nécessaire et ajoute au gonflement du code. Si quelque chose, vous pourriez potentiellement recommander la méthode réelle à partir de Fakerlaquelle sélectionne un élément de tableau aléatoire.
Pixxl
1
Un "problème simple" comme celui-ci est généralement résolu par des bibliothèques qui fournissent une solution simple à un problème auquel une centaine de personnes ont déjà dû faire face. Ces bibliothèques sont généralement robustes et bien déboguées et traitent de diverses mises en garde que nous ne voulons pas réimplémenter. Ce serait généralement la situation où je recommanderais d'utiliser une bibliothèque.
smonff
Alors vous devriez simplement copier cette méthode de la bibliothèque et la mettre dans un fichier utils
Rick Bross
Le conseil selon lequel les bibliothèques doivent être évaluées en termes de rapport coût / avantage du poids des pages WRT lorsqu'elles sont expédiées à un navigateur Web est un bon conseil et je suis entièrement d'accord pour dire que l'envoi de Faker.js à un navigateur serait ridicule. Cependant, la question ne mentionne pas le runtime JS utilisé. Pour un runtime basé sur NodeJS, des dépendances plus lourdes sont parfaitement raisonnables, ce qui est le cas lorsque j'utilise Faker.js - dans les suites de tests Cucumber JS.
Nathan
6

L'édition d'un prototype de tableau peut être nuisible. Ici, c'est une fonction simple pour faire le travail.

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
}

Usage:

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

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

Fonction récursive et autonome qui peut renvoyer n'importe quel nombre d'éléments (identique à 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])
}
habité
la source
2

Pour obtenir un tableau de forme d'élément aléatoire crypto-fort, utilisez

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
la source
1

Ceci est similaire, mais plus général, à la solution de @Jacob Relkin:

C'est ES2015:

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

Le code fonctionne en sélectionnant un nombre aléatoire entre 0 et la longueur du tableau, puis en renvoyant l'élément à cet index.

Max Heiber
la source
1

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

ou version plus courte équivalente:

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

Exemple de code:

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

Pavel P
la source
1

Fonction simple:

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

OU

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

OU

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
Dhakshith
la source
Il serait préférable de définir la variable myArrayy dans votre fonction pour ne pas polluer l'espace de noms global.
Neil Meyer
0

À mon avis, mieux que de jouer avec des prototypes ou de le déclarer juste à temps, je préfère l'exposer à la fenêtre:

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

Maintenant, n'importe où sur votre application, vous l'appelez comme:

var rand = window.choice.call(array)

De cette façon, vous pouvez toujours utiliser la for(x in array)boucle correctement

frankies
la source
1
Je n'étais pas là quand quelqu'un l'a voté, et je ne l'ai pas voté, mais je suppose que l'exposer à la fenêtre, c'est essentiellement déclarer une variable globale. Voir: stackoverflow.com/questions/2613310/…
Chris
1
Vous ne devriez jamais l'utiliser for...insur des tableaux, ni même en général. Vous courez le risque de marcher sur la chaîne du prototype. Il est également destiné à toutes les propriétés d'un objet, pas à tous les index d'un tableau. Si vous souhaitez utiliser un itérateur sur un tableau, utilisez for (var i = 0; i < foo.length; i++){}. Encore mieux, utilisez quelque chose comme à la Array.prototype.forEachplace.
Robert
1
Je ne préfère pas cela car cela pollue la portée mondiale. On pourrait dire que c'est peut-être le seul à être là, mais cela donnera des habitudes de violation de cette bonne pratique.
Jekk
0

J'ai trouvé un moyen de contourner les complications de la réponse supérieure, simplement en concaténant la variable rand à une autre variable qui permet d'afficher ce nombre à l'intérieur de l'appel de myArray [] ;. En supprimant le nouveau tableau créé et en jouant avec ses complications, j'ai trouvé une solution de travail:

<!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
la source
Je ne sais pas pourquoi concatchange jamais ici ... randomlui-même ne le change pas, et rien d'autre n'est appelé plus d'une fois ....
BalinKingOfMoria Reinstate CMs
1
Cette solution n'a aucun sens. Pourquoi créez-vous une variable appelée concat?
superluminaire
0

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

Vous définissez une variable constante sur le tableau, vous avez ensuite une autre constante qui choisit au hasard entre les trois objets du tableau, puis la fonction renvoie simplement les résultats.

Neil Meyer
la source
-1

Une façon générique d'obtenir des éléments aléatoires:

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
la source
-1

randojs rend cela un peu plus simple et lisible:

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

Aaron Plocharczyk
la source
1
Juste curieux: pourquoi les downvotes?
Leponzo
1
certaines personnes ne sont pas fan de sourcing dans les bibliothèques pour le code qu'ils pourraient écrire eux-mêmes, même si cela rendrait les choses plus rapides et plus lisibles. si la bibliothèque tombe en panne pour une raison quelconque, votre site Web a maintenant un problème. randojs ne descend pas, mais ils ne le savent pas parce que ce n'est pas aussi bien connu que des bibliothèques comme jQuery par exemple
Aaron Plocharczyk
-2

Voici un exemple de la façon de procéder:

$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
la source
-2

une autre méthode simple:

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

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

Créez une valeur aléatoire et passez au tableau

Veuillez essayer le code suivant.

//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
la source
5
Cette réponse utilise la même solution que la réponse déjà acceptée. Vous devez vous abstenir d'ajouter deux fois la même solution et n'évoquer à la place que d'autres alternatives possibles qui contribueraient davantage à la conversation.
Pixxl