1221

Consider:

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

How can I select a random value from this array using JavaScript?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Sarah
  • 12,401
  • 3
  • 17
  • 8

28 Answers28

2253

It's a simple one-liner:

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

For example:

const months = ["January", "February", "March", "April", "May", "June", "July"];

const random = Math.floor(Math.random() * months.length);
console.log(random, months[random]);
jakanz
  • 17
  • 6
Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
  • 10
    @SapphireSun this is correct. Note the `Math.floor(Math.random(...))` call, which rounds down. – ashes999 Jan 19 '14 at 12:43
  • 55
    Ahh, I've learned something new. I was discussing the case where it equals EXACTLY 1, but apparently (according to W3Schools) Math.random is between 0 inclusive and 1 exclusive. My bad. – SapphireSun Jan 20 '14 at 00:14
  • 14
    I might be wrong, but I recall `var rand = myArray[Math.random() * myArray.length>>0]` being slightly faster – vrugtehagel Jul 22 '16 at 12:34
  • 5
    I prefer this variant: `var rand = myArray[Math.random() * myArray.length | 0]` – np42 Aug 29 '18 at 15:54
  • Be aware that this function returns `undefined` as soon as you pass an empty array. It might be helpful to throw an exception in that case. – Froxx Jun 21 '22 at 23:38
128

If you've already got underscore or lodash included in your project you can use _.sample.

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

If you need to get more than one item randomly, you can pass that as a second argument in underscore:

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

or use the _.sampleSize method in lodash:

// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);
Brendan Nee
  • 5,087
  • 2
  • 33
  • 32
59

You may consider defining a function on the Array prototype, in order to create a method [].sample() which returns a random element.

First, to define the prototype function, place this snippet in your code:

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

Later, to sample a random element from the array, just call .sample():

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

I'm releasing these code snippets into the public domain, under the terms of the CC0 1.0 license.

Ben Aubin
  • 5,542
  • 2
  • 34
  • 54
  • 1
    And this does what? – Ken Sharp Jan 23 '18 at 01:26
  • 4
    @KenSharp it allows you to call `.sample()` on any array to get a random item – Ben Aubin Jan 23 '18 at 02:07
  • 30
    Extending native object types should be avoided. I have deleted my answer, seeing it was upvoted a lot, but promoting bad practice. For more discussion on this issue see e.g. https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice and https://eslint.org/docs/rules/no-extend-native – Markus Amalthea Magnuson Dec 06 '19 at 17:23
  • 4
    @MarkusAmaltheaMagnuson That's a good point. However, defining custom methods on prototypes isn't necessarily an issue, especially if done so sparingly and outside of library code. The prototype provides an alternative solution that is quite pretty (in my subjective opinion) and exposes sometimes-overlooked but interesting parts of the language, at least when used sparingly. For nearly all application code, this won't cause issues, so it comes down to a matter of taste. – Ben Aubin Jun 10 '21 at 21:18
  • See my own answer on extending the instance instead of the prototype. – Manngo Jan 07 '22 at 08:19
48

~~ is much faster than Math.Floor(), so when it comes to performance optimization while producing output using UI elements, ~~ wins the game. MORE INFO

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

But if you know that the array is going to have millions of elements then you might want to reconsider between Bitwise Operator and Math.Floor(), as bitwise operators behave weirdly with large numbers. See below example explained with the output.

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343
Ankur Soni
  • 5,725
  • 5
  • 50
  • 81
  • 1
    Link is dead, however interesting post and I shall be using this more than `Math.floor` now :) – alistair Aug 25 '19 at 08:12
  • 8
    using "bitwise not" operator, while faster, is not that readable, so you have to choose what is more important to you – Maciej Urbański Aug 29 '19 at 17:55
  • double tilda - interesting... I learned something new. – Gel Sep 27 '21 at 16:53
  • For those who want to understand what it means, `~` is a bitwise `not`, which reverses the `1`s and `0`s in a binary number. As with all bitwise operators, it first converts the number into a 32 bit integer, which all you really want. Using `~~` restores the original as a 32-bit integer. – Manngo Oct 26 '21 at 20:15
  • As for `Math.floor()`, All functions have an overhead which includes storing and restoring the original state. Generally, optimising compilers will look for opportunities to copy the code in place to avoid that overhead, but, with a dynamic language such as JavaScript, it’s harder to predict. – Manngo Oct 26 '21 at 20:18
42

The shortest version:

var myArray = ['January', 'February', 'March']; 
var rand = myArray[(Math.random() * myArray.length) | 0]
console.log(rand)
AATHITH RAJENDRAN
  • 4,689
  • 8
  • 34
  • 58
foxiris
  • 3,125
  • 32
  • 32
  • 6
    What does `| 0` do? – Ken Sharp Jan 23 '18 at 01:27
  • 6
    It will turn Float to Int, same as Math.floor. – foxiris Jan 23 '18 at 05:47
  • 5
    @KenSharp `| 0` itself is a bitwise operation that does nothing, but in javascript floats are [converted to ints before any bitwise operation](https://huytd.github.io/bitwise-float-int-trick.html). So it's something like how `+ ''` doesn't really do anything but can be used to convert things to strings. – dshepherd Sep 19 '18 at 07:26
  • 3
    It's not the same as `Math.floor` but it is the correct thing to do here. It's an operator so it's faster than `Math.floor` if only because at any time while running some code can do `Math.floor = someOtherFunction` and they can't do the same for '|'. On the other hand as for `Math.floor` and `|` being different try `Math.floor(-1.5)` vs `-1.5 | 0`. By the way you don't need the parentheses. `|` has a very low precedence. – gman Jun 05 '19 at 02:59
22

Say you want to choose a random item that is different from the last time (not really random, but still a common requirement)...

/**
 * Return a random element from an array that is
 * different than `last` (as long as the array has > 1 items). 
 * Return null if the array is empty.
*/
function getRandomDifferent(arr, last = undefined) {
  if (arr.length === 0) {
    return null;
  } else if (arr.length === 1) {
    return arr[0];
  } else {
    let num = 0;
    do {
      num = Math.floor(Math.random() * arr.length);
    } while (arr[num] === last);
    return arr[num];
  }
}

Implement like this:

const arr = [1,2,3];
const r1 = getRandomDifferent(arr);
const r2 = getRandomDifferent(arr, r1); // r2 is different than r1.
CrazyTim
  • 6,695
  • 6
  • 34
  • 55
13

If you have fixed values (like a month name list) and want a one-line solution

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

The second part of the array is an access operation as described in Why does [5,6,8,7][1,2] = 8 in JavaScript?

Community
  • 1
  • 1
I.G. Pascual
  • 5,818
  • 5
  • 42
  • 58
  • 11
    Such code is a bad and harmful practice. It should never be used in production. It has low readability and it has a hardcoded array length. The person changing the array input may forget to edit the length hardcoded in the end. – Seagull Sep 05 '18 at 22:50
  • 1
    @Seagull OP never asked for an specific environment. Also this comment is meaningless as it could be applied to almost all the answers in this question ;) – I.G. Pascual Sep 06 '18 at 14:36
  • But most people arrive to this question from Google search and the may use the solution in other scenarios than original OP. – Seagull Sep 09 '18 at 17:10
  • @Seagull Haha people are free to decide which approach to use, I'm not the clean code guideliness faq! – I.G. Pascual Sep 10 '18 at 15:45
  • 2
    I like the readability of this, just came to the same solution myself – Rauli Rajande Nov 28 '20 at 20:44
  • 1
    I fully agree, having to hardcode the array length this way is simply very bad coding, asking for maintenance issues... – Will59 Dec 29 '20 at 09:00
13

If you want to write it on one line, like Pascual's solution, another solution would be to write it using ES6's find function (based on the fact, that the probability of randomly selecting one out of n items is 1/n):

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

Use that approach for testing purposes and if there is a good reason to not save the array in a seperate variable only. Otherwise the other answers (floor(random()*length and using a seperate function) are your way to go.

Stephan
  • 2,028
  • 16
  • 19
12

Many of the offered solutions add a method to a specific Array which restricts it's use to just that array. This solution is reusable code that works for any array and can be made type safe.

TypeScript

export function randChoice<T>(arr: Array<T>): T {
  return arr[Math.floor(Math.random() * arr.length)]
}

JavaScript

function randChoice(arr) {
  return arr[Math.floor(Math.random() * arr.length)]
}
PauAI
  • 384
  • 4
  • 16
Tony O'Hagan
  • 21,638
  • 3
  • 67
  • 78
8

Editing Array prototype can be harmful. Here it is a simple function to do the job.

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);
Seagull
  • 3,319
  • 2
  • 31
  • 37
7

Faker.js has many utility functions for generating random test data. It is a good option in the context of a test suite:

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

As commenters have mentioned, you generally should not use this library in production code.

thoroc
  • 3,291
  • 2
  • 27
  • 34
Nathan
  • 5,272
  • 2
  • 26
  • 28
  • 17
    For a simple problem like this, adding a dependency for an entire library is unnecessary and adds to code bloat. If anything, you could potentially recommend the actual method from `Faker` which selects a random array element. – Pixxl Dec 21 '17 at 17:41
  • 2
    "Simple problem" like this one are usually solved by libraries that provide a simple solution to a problem that hundred of persons already had to face with. Those libraries are usually robust and well debugged and deals with various caveats we don't want to re-implement. It would be typically the situation where I would recommend to use a library. – smonff May 16 '18 at 07:59
  • Than you should just copy that one method from the library and put it in a utils file – Rick Bross Oct 01 '18 at 04:51
  • The advice that libraries should be assessed for cost/benefit WRT page weight when they are shipped to a web browser is sound advice and I whole-heartedly agree that shipping Faker.js to a browser would be ridiculous. However, the question does not mention which JS runtime is being used. For a NodeJS-based runtime heavier dependencies are perfectly reasonable which is the case for where I am using Faker.js - in Cucumber JS test suites. – Nathan Oct 03 '18 at 22:02
  • 1
    I'm working on tests that already use faker.js so this is a helpful answer to me. – Chris Jul 18 '22 at 18:41
7

If you need to fetch a random item more than once, then, obviously you would use a function. One way is to make that function a method of the Array.prototype, but that will normally get you shouted down for tampering with built in prototypes.

However, you can add the method to the specific array itself:

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

That way you can use months.random() as often as you like without interfering with the generic Array.prototype.

As with any random function, you run the risk of getting the same value successively. If you don’t want that, you will need to track the previous value with another property:

months.random=function() {
    var random;
    while((random=this[Math.floor(Math.random()*this.length)]) == this.previous);
    this.previous=random;
    return random;
};

If you’re going to do this sort of thing often, and you don’t want to tamper with Array.prototype, you can do something like this:

function randomValue() {
    return this[Math.floor(Math.random()*this.length)];
}

var data = [ … ];
var moreData = [ … ];

data.random=randomValue;
moreData.random=randomValue;
Manngo
  • 14,066
  • 10
  • 88
  • 110
5

To get crypto-strong random item form array use

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
  • 85,173
  • 29
  • 368
  • 345
4

Recursive, standalone function which can return any number of items (identical to 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])
}
dwilt
  • 617
  • 9
  • 13
2

This is similar to, but more general than, @Jacob Relkin's solution:

This is ES2015:

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

The code works by selecting a random number between 0 and the length of the array, then returning the item at that index.

Max Heiber
  • 14,346
  • 12
  • 59
  • 97
2

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

or equivalent shorter version:

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

Sample code:

var myArray = ['January', 'February', 'March'];    
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);
Pavel P
  • 15,789
  • 11
  • 79
  • 128
2

Simple Function :

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

OR

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

OR

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
Dhakshith
  • 66
  • 6
  • It would be better to set the myArrayy variable inside your function as to not pollute the global namespace. – Neil Meyer Mar 19 '18 at 08:07
0

In my opinion, better than messing around with prototypes , or declaring it just in time, I prefer exposing it to window:

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

Now anywhere on your app you call it like:

var rand = window.choice.call(array)

This way you can still use for(x in array) loop properly

weisk
  • 2,468
  • 1
  • 18
  • 18
  • 1
    I wasn't here when anyone downvoted it, and I didn't downvote it, but my guess is that exposing it to window is basically declaring a global variable. See: http://stackoverflow.com/questions/2613310/ive-heard-global-variables-are-bad-what-alternative-solution-should-i-use – Chris Apr 08 '15 at 21:30
  • 1
    You shouldn't ever use `for...in` on arrays, or even in general. You run the risk of walking the prototype chain. It's also meant for all properties of an object, not all indices in an array. If you want to use an iterator on an array, use `for (var i = 0; i < foo.length; i++){}`. Even better, use something like `Array.prototype.forEach` instead. – Robert Jan 18 '16 at 20:20
  • 1
    I do not prefer this because it pollutes the global scope. You could say this might be the only one to be there, but it will give habits of violating that good practice. – Jekk Nov 15 '16 at 05:43
0

I've found a way around the top answer's complications, just by concatenating the variable rand to another variable that allows that number to be displayed inside the calling of myArray[];. By deleting the new array created and toying around with it's complications, I've come up with a working solution:

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

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

You set a constant variable to the array, you then have another constant that chooses randomly between the three objects in the array and then the function simply returns the results.

Neil Meyer
  • 473
  • 4
  • 15
0

Looking for a true one-liner I came to this:

['January', 'February', 'March'].reduce((a, c, i, o) => { return o[Math.floor(Math.random() * Math.floor(o.length))]; })
blagus
  • 2,086
  • 4
  • 19
  • 22
0

By adding a method on prototype of array you can get random values easly.

In this example you can get single or multiple random values from array.

You can run to test code by clicking snippet button.

Array.prototype.random = function(n){
  if(n&&n>1){
    const a = [];
    for(let i = 0;i<n;i++){
      a.push(this[Math.floor(Math.random()*this.length)]);
    }
    return a;
  } else {
    return this[Math.floor(Math.random()*this.length)];
  }
}

const mySampleArray =  ['a','b','c','d','e','f','g','h'];

mySampleArray.random(); // return any random value etc. 'a', 'b'
mySampleArray.random(3); //retun an array with random values etc: ['b','f','a'] , ['d','b','d']

alert(mySampleArray.random());
alert(mySampleArray.random(3));
Kamuran Sönecek
  • 3,293
  • 2
  • 30
  • 57
0

Method 1:

  • Use Math.random() function to get the random number between(0-1, 1 exclusive).
  • Multiply it by the array length to get the numbers between(0-arrayLength).
  • Use Math.floor() to get the index ranging from(0 to arrayLength-1).

const arr = ["foo","bar"];
const randomlyPickedString=arr[Math.floor(Math.random() * arr.length)]; console.log(randomlyPickedString);

Method 2:

  • The random(a, b) method is used to generates a number between(a to b, b exclusive).
  • Taking the floor value to range the numbers from (1 to arrayLength).
  • Subtract 1 to get the index ranging from(0 to arrayLength-1).

const arr = ["foo","bar"];
const randomlyPickedString=arr[Math.floor(random(1, 5))-1]; console.log(randomlyPickedString);

Abdulmoiz Ahmer
  • 1,953
  • 17
  • 39
-1

A generic way to get random element(s):

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
  • 7,605
  • 13
  • 31
  • 46
-2

Here is an example of how to do it:

$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)];
mech
  • 2,775
  • 5
  • 30
  • 38
varun
  • 1
-3

Create one random value and pass to array

Please try following code..

//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);
  • 6
    This answer uses the same solution as the already accepted answer. You should refrain from adding the same solution twice and instead only bring up possible other alternatives that would contribute more to the conversation. – Pixxl Dec 21 '17 at 17:44
-3

randojs makes this a little more simple and readable:

console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>
Aaron Plocharczyk
  • 2,776
  • 2
  • 7
  • 15
  • 1
    some people aren't a fan of sourcing in libraries for code they could write themselves, even if it would make things faster and more readable. if the library goes down for some reason, your website now has a glitch. randojs doesn't go down, but they don't know that because it's not as well known as libraries like jQuery for example – Aaron Plocharczyk Feb 21 '20 at 02:56
-6

I am really surprised nobody tried to use native random values:

array[Date.now()%array.length]

It will not work for array length over 160000000000, but I am sure you will never create arrays like this

UPD

As far as you question is how to pick random value from array called myArray (with len=3), the solution should be:

myArray[Date.now()%myArray.length]
Egor
  • 279
  • 5
  • 21
  • I didn’t downvote you, but I can’t see how your solution is in any related to the question. I assume other’s can’t either. – Manngo Jan 07 '22 at 08:17
  • So .. yes it "kind of" works, but then again not really. It's being downvoted because `Date.now()` has nothing to do with randomness and is quite deterministic indeed. I get that it might feel "random" enough in some use-cases though – nuts Feb 15 '22 at 14:25
  • @nuts `Date.now()` everytime returns different values, this way it cannot be detemined for 100% accurace, moreover in case for array about 3 elements. – Egor Feb 15 '22 at 15:25
  • 2
    @EgorRandomize these Date-values are highly deterministic. That is the oppositve of random. Again: Yes, as a user you get perceived randomness, but it has nothing to do with actual randomness. (Btw: I didn't even downvote ^^) – nuts Feb 15 '22 at 17:18
  • @nuts yes, I agree with your thoughts, but how can I tag my question as another view-point? Because here I can see only `Math.Rand` implemented solutions, as far as it is one pseudo-random function – Egor Feb 15 '22 at 17:25
  • 1
    Downvoted, because it's *not random*, and not an appropriate answer. – Brad Oct 30 '22 at 00:09
  • @Brad how can you prove it? This is literally the most appropriate answer & the shortest answer. – Egor Nov 08 '22 at 12:16
  • 3
    @Egor Do we really need proof beyond the obvious that time is deterministic? Fine... call it in a loop and watch all the repeated values you get. It's a bad side effect that will bite you at some point... if not today, it will in the future. It's like, what, 15 extra characters of typing to do it the right way? – Brad Nov 09 '22 at 20:05
  • @Brad who was talking about loops? Where 15 extra chars came from? There are no such factors in original question. We have 3 different cases and one attempt to take one of them. Millisecond logic is perfect for this particular situation. – Egor Nov 10 '22 at 05:32
  • 3
    @Egor The question is generic and highly referenced. It simply asks how to get a random value from an array. Your answer does not return a **random value** from an array. You asked for proof that your answer is not random. I gave it to you, with a very clear and common example. If your answer had some tradeoff of determinism-for-other-goodness, and if you called out that tradeoff in your answer, it'd be appropriate. Instead, you've tacked on a bad answer to a decade-old question, that has no advantage over one of the several good answers already posted. Hence, my downvote. – Brad Nov 10 '22 at 05:38