1277
var items = Array(523, 3452, 334, 31, ..., 5346);

How do I get random item from items?

K-Gun
  • 10,689
  • 2
  • 52
  • 56
James
  • 38,737
  • 52
  • 130
  • 161
  • 401
    the answer will not involve jQuery – Alnitak May 06 '11 at 17:51
  • 53
    I've never seen so many absolutely identical responses to a question... – Blindy May 06 '11 at 17:52
  • 11
    great minds, @Blindy – Kelly May 06 '11 at 17:54
  • only this one involved numbers instead of months, eh? :-P – Kelly May 06 '11 at 17:57
  • 36
    I found a way to involve jQuery!! (see my second answer) – Alnitak May 06 '11 at 18:10
  • 11
    This question is absolutely identical to [Getting random value from an array](http://stackoverflow.com/questions/4550505/getting-random-value-from-an-array), yet the Mighty Mods haven't bothered to close it in 3+ years. Instead, they close ["unconstructive" questions with hundreds of votes](http://stackoverflow.com/questions/10099059/what-are-the-key-differences-between-meteor-ember-js-and-backbone-js). – Dan Dascalescu Dec 16 '14 at 11:01
  • This now has more votes than the "unconstructive" question. –  Feb 22 '17 at 14:34
  • All answers to this problem are fundamentally wrong from what I can see and each basically just copy the others. What happens if the array has had elements deleted ([0],[1],[3],[4]...)? What happens if elements are added in way that keys are not an consistently incremented value but instead have some other meaning (such as a unique user id ([3453],[4316],[73698],[924]...). Are people so stuck on how to correctly use Math.random() that they are overlooking this? – JSON Sep 06 '18 at 04:35

13 Answers13

2692
var item = items[Math.floor(Math.random()*items.length)];
Corey
  • 6,218
  • 4
  • 19
  • 28
Kelly
  • 36,733
  • 4
  • 39
  • 51
  • 1
    If I copy/paste this into my source, I'm getting an 'Uncaught SyntaxError: Unexpected token' in my browser. Are there any rogue hidden characters that get copied from SO answers? – Abhranil Das Oct 01 '12 at 11:52
  • 162
    **Math.random() will never be 1, nor should it.** The largest index should always be one less than the length, or else you'll get an `undefined` error. – Kelly Sep 16 '13 at 16:06
  • 31
    Elegant solution. I tested it: `var items = ["a","e","i","o","u"]` `var objResults = {}` `for(var i = 0; i < 1000000; i++){` `var randomElement = items[Math.floor(Math.random()*items.length)]` `if (objResults[randomElement]){` `objResults[randomElement]++` `}else{` `objResults[randomElement] = 1` `}` `}` `console.log(objResults)` The results are pretty randomized after 1000000 iterations: `Object {u: 200222, o: 199543, a: 199936, e: 200183, i: 200116}` – Johann Echavarria May 01 '14 at 22:17
  • 6
    @AnkitPatial: That's a way to "scramble" an array, but the question is about getting a randomly selected element from an array. There's a big difference. – damd Mar 04 '16 at 15:04
  • @damd you are right my reference is not for single item access scenario. But its perfect if you want to iterate full array in random fashion, which was my case. – Ankit Patial Mar 07 '16 at 12:14
  • I might be wrong, but I recall `var item = items[Math.random()*items.length>>0]` being slightly faster – vrugtehagel Jul 22 '16 at 12:31
  • 2
    What happens here when array is empty? – tomazahlin Oct 21 '16 at 16:02
  • Sorry, I must down vote this answer because: Use Math.round must more precisely than Math.floor. You can test on the console: Math.floor(Math.random()) => 0 Math.floor(Math.random()) => 0 Math.floor(Math.random()) => 0 Math.floor(Math.random()) => 0 Math.floor(Math.random()) => 0 Be careful. – christian Nguyen Dec 20 '16 at 09:38
  • 21
    @virus `Math.round` is not a valid substitution for `Math.floor`. Using `round` would cause accidentally referencing an undefined index, say in the case `Math.random()` is 0.95 and `items.length` is 5. `Math.round(0.95*5)` is 5, which would be an invalid index. `floor(random)` will always be zero in your example. – Kelly Dec 20 '16 at 14:43
  • 1
    @tomazahlin, if the array is empty, it will try to get item 0, which will fail. – Solomon Ucko Apr 02 '17 at 19:39
  • Nice and simple solution. Thanks! – Tsurule Vol Nov 10 '17 at 08:13
  • 21
    Nice answer. You can be shorter: `items[items.length * Math.random() | 0]` :) – aloisdg Mar 19 '18 at 17:20
  • 3
    @aloisdg that's true, as long as the array length is less than 2^31, which is still a very large number :) – Kelly Mar 21 '18 at 21:22
  • @Kelly it should be fine :) – aloisdg Mar 22 '18 at 09:38
  • Thanks! Is it possible to ignore repetition of randomly chosen items? – Ulvi Jan 10 '21 at 12:45
  • 1
    @Ulvi I believe the best way to do this would be to either remove the chosen item from the array or have a set that contains all chosen items and look in the set to see if the currently selected element exists within it already. – DeveloperRyan Feb 03 '21 at 02:26
123

Use underscore (or loDash :)):

var randomArray = [
   '#cc0000','#00cc00', '#0000cc'
];

// use _.sample
var randomElement = _.sample(randomArray);

// manually use _.random
var randomElement = randomArray[_.random(randomArray.length-1)];

Or to shuffle an entire array:

// use underscore's shuffle function
var firstRandomElement = _.shuffle(randomArray)[0];
chim
  • 8,095
  • 3
  • 49
  • 59
  • 40
    Using underscore or lodash for just one function would be overkill, but if you're doing any complicated js functionality then it can save hours or even days. – chim Jan 07 '13 at 09:43
  • 1
    If the minimum value for underscore's `random` method is 0 it needs only the max value. [Docs here](http://underscorejs.org/#random) – Aaron Apr 03 '13 at 19:06
  • 26
    Nowadays underscore has also better choice for this ```_.sample([1, 2, 3, 4, 5, 6])``` – Mikael Lepistö Dec 03 '13 at 08:43
  • 7
    You will probably be using _ on any real project. It's not a bad thing. – superluminary Jul 14 '15 at 19:17
  • 8
    lodash is modularized on npm, so you can install just the `sample` function if you want: https://www.npmjs.com/package/lodash.sample – XåpplI'-I0llwlg'I - Dec 04 '15 at 11:32
  • 2
    `npm i -S lodash.sample` -- Love modular lodash w/browserify! – Roy Mar 10 '16 at 19:10
  • 7
    My creed is to use as few libraries as possible for any project. With that being said, I always end up using lodash. It's too convenient to not use – Phil Andrews Dec 09 '16 at 20:21
  • 1
    My emoji, list and parenthesis interpreters all gave different results for `:)):`, so I don't quite understand the first line. –  Feb 22 '17 at 14:35
  • 1
    `_.shuffle(randomArray)[0];` This can return undefined values – Gimnath Mar 27 '22 at 02:34
113

1. solution: define Array prototype

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

that will work on inline arrays

[2,3,5].random()

and of course predefined arrays

var list = [2,3,5]
list.random()

2. solution: define custom function that accepts list and returns element

function get_random (list) {
  return list[Math.floor((Math.random()*list.length))];
}


get_random([2,3,5])
JUDE DAILY
  • 122
  • 9
Dino Reic
  • 3,051
  • 3
  • 21
  • 11
  • 37
    @EvanCarroll better reference a useful link instead of downvoting for subjective notions such as coding style which does not make the answer invalid nor "unuseful" ! https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice – Simon Jul 14 '17 at 19:19
  • 31
    Upvoted because downvoting for adding something to Array.prototype is not useful to anyone without explanation. – AlexanderGriffin Nov 04 '18 at 18:20
  • 3
    The issue with adding a new function to Array.prototype is the same issue as adding a global variable - someone/something else may be using the same "name" for something different - which can cause subtle mahem – Schmoo Jun 27 '20 at 06:43
  • 1
    Thank you for this. Far more *usable* than typing the whole vanilla formula or calling a custom function when the code requires it more than once. As for the valid concerns about conflicts, that's what namespacing is for: `ns.` or `ns_` format where applicable. – OXiGEN Sep 21 '20 at 02:13
  • 1
    @Schmoo I just ran into one of those "subtle mayhem" situations. I shortened the prototype's name to "rand". Then suddenly during a `for (let i in arr)` loop, it iterates all the expected indexes, and also iterates an index of "rand". Had to switch to a `for (let i=0,l=arr.length;i – OXiGEN Sep 21 '20 at 09:24
  • Ditto @AlexanderGriffin. There is nothing wrong with adding to `Array.prototype` as long as the project doesn’t have to interact with other libraries or fight with other developers. There’s nothing _technically_ wrong with it anyway, but there might be logistic concerns where are the only real objections to that sort of thing. – Manngo Jul 12 '21 at 02:37
  • While we’re at it, we can always add the randomising method to the array itself: `items.random=function() {return this[Math.floor(Math.random()*this.length)];}`. This way you call the method as `items.random()` without getting into a religious war over tampering with prototypes. – Manngo Jul 12 '21 at 03:24
105

If you really must use jQuery to solve this problem (NB: you shouldn't):

(function($) {
    $.rand = function(arg) {
        if ($.isArray(arg)) {
            return arg[$.rand(arg.length)];
        } else if (typeof arg === "number") {
            return Math.floor(Math.random() * arg);
        } else {
            return 4;  // chosen by fair dice roll
        }
    };
})(jQuery);

var items = [523, 3452, 334, 31, ..., 5346];
var item = jQuery.rand(items);

This plugin will return a random element if given an array, or a value from [0 .. n) given a number, or given anything else, a guaranteed random value!

For extra fun, the array return is generated by calling the function recursively based on the array's length :)

Working demo at http://jsfiddle.net/2eyQX/

Alnitak
  • 325,660
  • 70
  • 395
  • 481
  • 3
    @neoascetic the point of that line is that picking an element from an array is not a jQuery problem, it's generic JS. – Alnitak Feb 10 '14 at 13:51
  • 114
    +1 for the fair dice roll! [For those poor souls who don't get the joke.](http://xkcd.com/221/) – The Guy with The Hat Aug 19 '14 at 13:16
  • @damd re: your proposed edit - it was clearly incorrect, since there's a clear split between _defining_ the plugin in the IIFE, and using the plugin. However for consistency I have replaced the `$` in the usage line with `jQuery`. – Alnitak Mar 04 '16 at 15:54
  • 4
    Definitely. There are less than an average of 3 chained methods per line, and the `$` is not being used at least once per each line, therefore it does not have enough jQuery. –  Feb 22 '17 at 14:47
  • 2
    This is not a problem that requires jQuery. – robertmain Feb 01 '19 at 14:57
  • @robertmain see first line – Alnitak Feb 01 '19 at 15:17
  • I saw it. I'm still sticking with my comment. This problem does not require jQuery. Any more than addition, string concatenation, variable interpolation or sorting does. – robertmain Feb 01 '19 at 16:43
  • https://needsmorejquery.com/ – easrng May 06 '20 at 01:12
  • return 4.... Not only that, but you NEVER "have to use jQuery", it's not a tool that is in the space where it solves things nothing else can any more. – MrMesees Aug 23 '20 at 07:54
66

Here's yet another way:

function rand(items) {
    // "~~" for a closest "int"
    return items[~~(items.length * Math.random())];
}

Or as recommended below by @1248177:

function rand(items) {
    // "|" for a kinda "int div"
    return items[items.length * Math.random() | 0];
}
K-Gun
  • 10,689
  • 2
  • 52
  • 56
  • 43
    What is that crazy `~~`? Never seen that in JS before. – Sam Stern Nov 22 '14 at 22:20
  • 10
    @hatboysam: [do a search](http://stackoverflow.com/questions/4055633/what-does-double-tilde-do-in-javascript) - it essentially converts the operand to the closest integer. – Dan Dascalescu Dec 16 '14 at 11:10
  • 9
    Actually, it rounds it down, like `Math.floor`. –  Feb 22 '17 at 14:36
  • 19
    Nice answer. You still can be shorter: `items[items.length * Math.random() | 0]` :) – aloisdg Mar 19 '18 at 17:19
  • 12
    "Actually, it rounds it down, like Math.floor" @programmer5000. It actually rounds towards 0, i.e. ~~(-1.5) evaluates to -1, not the -2 which Math.floor gives. – Eureka Jul 22 '18 at 16:08
  • `~~5.999999999999999` outputs `5` whereas `~~5.9999999999999999` outputs `6`... heh – evolutionxbox Aug 29 '20 at 17:08
  • @SamStern `~~` is a trick to remove decimals by converting a number to an integer. See https://stackoverflow.com/questions/4055633/what-does-double-tilde-do-in-javascript#answer-4055675 – Manngo Jul 12 '21 at 02:45
  • @evolutionxbox That’s due to a round off error that you get with JavaScript. It’s similar to the notorious `0.1+0.2` error. Remember that decimals, being based on `2`s and `5`s often convert to recurring “binary decimals” (bicimals?) since binary is based only on `2`s. – Manngo Jul 12 '21 at 02:48
  • ~ is a bitwise NOT operator: [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT). Here it is used twice, similar like `!!some_variable`. – cezar Oct 10 '21 at 07:30
52
var random = items[Math.floor(Math.random()*items.length)]
gen_Eric
  • 214,658
  • 40
  • 293
  • 332
20

jQuery is JavaScript! It's just a JavaScript framework. So to find a random item, just use plain old JavaScript, for example,

var randomItem = items[Math.floor(Math.random()*items.length)]
Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
planetjones
  • 12,109
  • 4
  • 48
  • 51
15
var rndval=items[Math.floor(Math.random()*items.length)];
Blindy
  • 60,429
  • 9
  • 84
  • 123
14
// 1. Random shuffle items
items.sort(function() {return 0.5 - Math.random()})

// 2. Get first item
var item = items[0]

Shorter:

var item = items.sort(function() {return 0.5 - Math.random()})[0];

Even shoter (by José dB.):

let item = items.sort(() => 0.5 - Math.random())[0];
Ivan Pirog
  • 2,656
  • 1
  • 15
  • 7
9
var items = Array(523,3452,334,31,...5346);

function rand(min, max) {
  var offset = min;
  var range = (max - min) + 1;

  var randomNumber = Math.floor( Math.random() * range) + offset;
  return randomNumber;
}


randomNumber = rand(0, items.length - 1);

randomItem = items[randomNumber];

credit:

Javascript Function: Random Number Generator

Martijn Pieters
  • 963,270
  • 265
  • 3,804
  • 3,187
neebz
  • 11,249
  • 7
  • 46
  • 62
6

If you are using node.js, you can use unique-random-array. It simply picks something random from an array.

Aayan L
  • 77
  • 1
  • 6
2

An alternate way would be to add a method to the Array prototype:

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

 var teams = ['patriots', 'colts', 'jets', 'texans', 'ravens', 'broncos']
 var chosen_team = teams.random(teams.length)
 alert(chosen_team)
Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
James Daly
  • 1,368
  • 14
  • 25
  • 4
    arrays have a built-in length property - why pass it as a parameter?! – Alnitak Dec 24 '12 at 18:22
  • 1
    i guess my point is that you can pass in any length you want not just the length of the array - if you just wanted to randomize the first two entries you could put length as 2 without changing the method. I don't think there is a performance issue with passing the length property as a parameter but i may be wrong – James Daly Dec 24 '12 at 19:15
  • 2
    It is generally not a good idea to extend host objects like this. You risk tripping over a future implementation of `Array.random` by the client that behaves differently than yours, breaking future code. You could at least check to make sure it doesn't exist before adding it. – Chris Baker Aug 19 '14 at 18:36
1
const ArrayRandomModule = {
  // get random item from array
  random: function (array) {
    return array[Math.random() * array.length | 0];
  },

  // [mutate]: extract from given array a random item
  pick: function (array, i) {
    return array.splice(i >= 0 ? i : Math.random() * array.length | 0, 1)[0];
  },

  // [mutate]: shuffle the given array
  shuffle: function (array) {
    for (var i = array.length; i > 0; --i)
      array.push(array.splice(Math.random() * i | 0, 1)[0]);
    return array;
  }
}
Nicolas
  • 607
  • 5
  • 11
  • Pointed out in many comments, this is a bad practice, please refer to https://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice :) – benftwc Aug 28 '18 at 00:12
  • I just change the declaration to avoid showing bad pactice method declaration – Nicolas Aug 29 '18 at 15:52