1272

Consider:

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

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

1
  • Future visitors: Please only add an answer if it's actually an original innovation, not a slight adjustment to an existing answer, especially if it recommends a poor practice like modifying the array prototype, creating globals, using your brand new third party package, something that runs in O(n), etc. Thanks.
    – ggorlen
    Commented Jul 7 at 15:46

18 Answers 18

2311

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

5
  • 10
    @SapphireSun this is correct. Note the Math.floor(Math.random(...)) call, which rounds down.
    – ashes999
    Commented Jan 19, 2014 at 12:43
  • 56
    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. Commented Jan 20, 2014 at 0:14
  • 14
    I might be wrong, but I recall var rand = myArray[Math.random() * myArray.length>>0] being slightly faster
    – user3546284
    Commented Jul 22, 2016 at 12:34
  • 5
    I prefer this variant: var rand = myArray[Math.random() * myArray.length | 0]
    – np42
    Commented Aug 29, 2018 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
    Commented Jun 21, 2022 at 23:38
137

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);
1
  • 4
    When using typescript: Be aware that the return type would be "string | undefined" instead of "string" given a string array. Commented May 6, 2020 at 18:18
61

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.

5
  • 1
    And this does what?
    – Ken Sharp
    Commented Jan 23, 2018 at 1:26
  • 4
    @KenSharp it allows you to call .sample() on any array to get a random item
    – Ben Aubin
    Commented Jan 23, 2018 at 2:07
  • 33
    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. stackoverflow.com/questions/14034180/… and eslint.org/docs/rules/no-extend-native Commented Dec 6, 2019 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
    Commented Jun 10, 2021 at 21:18
  • See my own answer on extending the instance instead of the prototype.
    – Manngo
    Commented Jan 7, 2022 at 8:19
51

~~ 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
5
  • 1
    Link is dead, however interesting post and I shall be using this more than Math.floor now :)
    – alistair
    Commented Aug 25, 2019 at 8:12
  • 9
    using "bitwise not" operator, while faster, is not that readable, so you have to choose what is more important to you Commented Aug 29, 2019 at 17:55
  • double tilda - interesting... I learned something new.
    – Gel
    Commented Sep 27, 2021 at 16:53
  • For those who want to understand what it means, ~ is a bitwise not, which reverses the 1s and 0s 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
    Commented Oct 26, 2021 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
    Commented Oct 26, 2021 at 20:18
44

The shortest version:

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

4
  • 6
    What does | 0 do?
    – Ken Sharp
    Commented Jan 23, 2018 at 1:27
  • 6
    It will turn Float to Int, same as Math.floor.
    – foxiris
    Commented Jan 23, 2018 at 5:47
  • 7
    @KenSharp | 0 itself is a bitwise operation that does nothing, but in javascript floats are converted to ints before any bitwise operation. So it's something like how + '' doesn't really do anything but can be used to convert things to strings.
    – dshepherd
    Commented Sep 19, 2018 at 7: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
    Commented Jun 5, 2019 at 2: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.
0
16

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

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?

7
  • 12
    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
    Commented Sep 5, 2018 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 ;) Commented Sep 6, 2018 at 14:36
  • 1
    But most people arrive to this question from Google search and the may use the solution in other scenarios than original OP.
    – Seagull
    Commented Sep 9, 2018 at 17:10
  • 2
    I like the readability of this, just came to the same solution myself Commented Nov 28, 2020 at 20:44
  • 2
    I fully agree, having to hardcode the array length this way is simply very bad coding, asking for maintenance issues...
    – Will59
    Commented Dec 29, 2020 at 9:00
9

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.

6
  • 18
    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
    Commented Dec 21, 2017 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
    Commented May 16, 2018 at 7:59
  • Than you should just copy that one method from the library and put it in a utils file
    – Rick Bross
    Commented Oct 1, 2018 at 4: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
    Commented Oct 3, 2018 at 22:02
  • 2
    I'm working on tests that already use faker.js so this is a helpful answer to me.
    – Chris
    Commented Jul 18, 2022 at 18:41
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);
1
  • The if (arr && arr.length) { check isn't necessary--indexing out of bounds will return undefined, so this is essentially a micro optimization to avoid a couple of already-optimized function calls for a rare edge case. Once you remove that, this is identical to dozens of existing answers. I suggest deletion.
    – ggorlen
    Commented Jul 7 at 15:41
6

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;
3
  • Never modify core library prototypes.
    – ggorlen
    Commented Jul 7 at 15:21
  • @ggorlen Thanks for the mantra. It’s a good thing that this solution doesn’t do that. It adds a method to an existing object without reaching out to the prototype.
    – Manngo
    Commented Jul 8 at 7:47
  • I see--sorry for not reading more carefully. Nonetheless, I don't see the improvement. If random is ever added to the core array, your app will likely break just the same, and it's still unreadable and confusing for other programmers, so it reduces to the same issues as tampering with the prototype. The while loop you showed will run infinitely if the array length is 1, and avoiding repeated random choices is an unrelated requirement. Basically: future visitors should avoid this answer completely--it's misleading, providing a ton of potential footguns with no syntactical benefits.
    – ggorlen
    Commented Jul 8 at 14:31
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) )

Additional info from mdn:

Note: Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the Crypto.getRandomValues() method.

3
  • What benefit does this offer over the Math.random() solution? Security, presumably? When should I use it?
    – ggorlen
    Commented Jul 7 at 15:21
  • @ggorlen quote from mdn Math.random: "Note: Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the Crypto.getRandomValues() method" Commented Jul 7 at 18:59
  • Great, thanks. Please edit that into your answer and flag my comments for removal.
    – ggorlen
    Commented Jul 7 at 19:34
3

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])
}
1
  • Recursion is inappropriate here--this will blow the stack on arrays larger than a few thousand elements. It's also not what OP's asking.
    – ggorlen
    Commented Jul 7 at 15:19
1

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.

1
  • This is identical to dozens of other answers.
    – ggorlen
    Commented Jul 7 at 15:17
1

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

1
  • Identical to dozens of other answers. Suggest deletion.
    – ggorlen
    Commented Jul 7 at 15:45
1

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();
2
  • It would be better to set the myArrayy variable inside your function as to not pollute the global namespace.
    – Neil Meyer
    Commented Mar 19, 2018 at 8:07
  • Both code snippets are confusing because of the order of delcarations (I suggest grouping the 'main' code together, not spreading it out above and below the function definition), but especially the second, which breaks encapsulation of the function relying on a global. No need for this to exist--dozens of other answers are identical functionally (but cleaner).
    – ggorlen
    Commented Jul 7 at 15:18
0
MyArray.at(MyArray.length*Math.random())

I find this both concise and clear. Requires ES2022.

2
  • Somebody suggest an edit with Math.floor() first to get an integer. It's more correct... yet so far on all implementations I tested, this does work. Because my goal here is remaining compass I rejected the suggestion, but it's good to at least mention it so thanks.
    – Utopiah
    Commented May 31 at 6:57
  • You might want to edit the answer to mention that [].at(float) floors the float/decimal number returned by .length * Math.random(), which is why it works. Can you also provide evidence that this is in the spec and can be relied on universally, not an implementation detail?
    – ggorlen
    Commented Jul 7 at 15:14
-1

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

1
  • Don't extent prototypes.
    – ggorlen
    Commented Jul 7 at 15:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.