34

I'm reading a beginner's JavaScript book with some code that compares the coder's input (var answer) to a randomly chosen string from an array (answers). It's a guessing game.

I am confused about the way a string is chosen randomly. The code appears to be multiplying the Math.random function by the answers array and its length property. Checking around, this appears to be the standard way to make a random selection from an array? Why would you use a math operator, the *, to multiply... out... a random string based on an array's length? Isn't the length technically just 3 strings? I just feel like it should be something simple like index = answers.random. Does that exist in JS or another language?

<script>

var guess = "red";
var answer = null;

var answers = [ "red",
"green",
"blue"];

var index = Math.floor(Math.random() * answers.length);

if (guess == answers[index]) {
answer = "Yes! I was thinking " + answers[index];
} else {
answer = "No. I was thinking " + answers[index];
}
alert(answer);

</script>
PeeHaa
  • 71,436
  • 58
  • 190
  • 262
nicedwar
  • 465
  • 1
  • 4
  • 5
  • 2
    possible duplicate of [Getting random value from an array](http://stackoverflow.com/questions/4550505/getting-random-value-from-an-array) – PeeHaa Jan 30 '12 at 22:14
  • 7
    Not exactly. user1179078 already has the answer, but wants to know why it works. – JimmiTh Jan 30 '12 at 22:21

11 Answers11

50

It's easy in Python.

>>> import random
>>> random.choice(['red','green','blue'])
'green'

The reason the code you're looking at is so common is that typically, when you're talking about a random variable in statistics, it has a range of [0,1). Think of it as a percent, if you'd like. To make this percent suitable for choosing a random element, you multiply it by the range, allowing the new value to be between [0,RANGE). The Math.floor() makes certain that the number is an integer, since decimals don't make sense when used as indices in an array.

You could easily write a similar function in Javascript using your code, and I'm sure there are plenty of JS utility libraries that include one. Something like

function choose(choices) {
  var index = Math.floor(Math.random() * choices.length);
  return choices[index];
}

Then you can simply write choose(answers) to get a random color.

Matt Luongo
  • 14,371
  • 6
  • 53
  • 64
25

Here you go

function randomChoice(arr) {
    return arr[Math.floor(arr.length * Math.random())];
}
scottmrogowski
  • 2,063
  • 4
  • 23
  • 32
  • 3
    Math.random() will return a number between 0 and 1, multiply that number by the array length and the biggest it could possibly be is the array length, however it will have a decimal if random didn't return exactly 1. Math.floor() removes that decimal if it exists and does nothing otherwise. – Lotus Jul 24 '15 at 00:40
24

Math.random gives you a random number between 0 and 1.

Multiplying this value by the length of your array will give you a number strictly less than the length of your array.

Calling Math.floor on that will truncate the decimal, and give you a random number within the bounds of your array

var arr = [1, 2, 3, 4, 5];
//array length = 5;

var rand = Math.random();
//rand = 0.78;
rand *= arr.length; //(5)
//rand = 3.9
rand = Math.floor(rand);
//rand = 3

var arr = [1, 2, 3, 4, 5];
//array length = 5;

var rand = Math.random();
//rand = 0.9999;
rand *= arr.length; //(5)
//rand = 4.9995
rand = Math.floor(rand);
//rand = 4 - safely within the bounds of your array
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
  • Oh I see. It sounds like each item in an array is actually a number. So I have to generate a decimal, multiply that by an array item's number, then round that down, get it translated back to a string and compare that to the string that was input. That sure is complex. – nicedwar Jan 30 '12 at 22:25
  • A point that's often missed, is that Math.random may return 0, but never returns 1 (as you say, "strictly less than the length of your array"). Which is why it works so nicely multiplying by length (length is 5, but we want a number between 0 and 4). Seen lots of examples of even experienced programmers forgetting that point as soon as it's not about array indices, but other random integers. E.g., using Math.random() * 10 (wrong) rather than 11 (correct) to get a random integer between 0 and 10. – JimmiTh Jan 30 '12 at 22:27
  • @nicedwar - not quite. Arrays are indexed by integers. The first array member is arr[0] the next is arr[1] and so on, up to arr[arr.length - 1]. You need to get a random number in the range [0, arr.length - 1] and the algorithm above does that. Once you have that number, you can index the array with it. – Adam Rackis Jan 30 '12 at 22:28
  • @JimmiTh: From MDN: *If extremely large bounds are chosen (2^53 or higher), it's possible in extremely rare cases to calculate the usually-excluded upper bound.* –  Feb 25 '15 at 09:59
2

Popular Underscore javascript library provides function for this, which can be used similar to python's random.choice :

http://underscorejs.org/#sample

var random_sample = _.sample([1, 2, 3, 4, 5, 6]);
Mikael Lepistö
  • 18,909
  • 3
  • 68
  • 70
2

JavaScript

No. Vanilla JS does not provide any method like the following. You have to calculate, unfortunately.

function sample(array) {
  return array[Math.floor(Math.random() * array.length)];
}

console.log(sample([1, 2, 3]));
console.log(sample([11, 22.3, "33", {"a": 44}]));

Try it out here.

But, if you are using lodash, the above method is already covered.

let _ = require('lodash');

console.log(_.sample([11, 22.3, "33", {"a": 44}]));

Try it out here.

Python

import random
random.choice([1, 2.3, '3'])

Try it out here.

Ruby

using a single data type,

[1, 2, 3].sample

using multiple data types,

[1, 2.34, 'a', "b c", [5, 6]].sample

Try it out here.

Updated: JavaScript example added.

Shakil
  • 1,044
  • 11
  • 17
1
var choiceIndex = Math.floor(Math.random() * yourArray.length)
Freestyle076
  • 1,548
  • 19
  • 36
1

GoLang:

Simply get a random number (within the range of the array) and select an item from the array like:

array := []string{ "item1" , "item2" , "item3" }
n := rand.Intn(len(reasons))
fmt.Print("The random item is: ", array[n])
1

Math.random and similar functions usually return a number between 0 and 1. As such, if you multiply the random number by your highest possible value N, you'll end up with a random number between 0 and N.

CanSpice
  • 34,814
  • 10
  • 72
  • 86
0

i tested the different possibilty for each element and this is better because every one has same Possibility:

classMates = ["bb", "gg", "jj", "pp", "hh"];
k = classMates.length - 0.5;
function ran(){
    p = Math.round(Math.random() * k);
    console.log(classMates[p])
}
ran()
shadow-light
  • 447
  • 5
  • 7
0

When it's only array is simple, but when we have an object we can do in this way:

function random_choice(array, isObject = false){
        if(isObject){
            const len = Object.keys(array);
            const rand = Math.floor(Math.random() * len.length);
            for (let l = 0; l < len.length; l++) {
                if (l == rand) {
                    return array[len[l]];
                }
            }
        } else {
            const rand = Math.floor(Math.random() * array.length);
            for (let l = 0; l < array.length; l++) {
                if (l == rand) {
                    return array[l];
                }
            }
        }
    }

Example:

function random_choice(array, isObject = false){
            if(isObject){
                const len = Object.keys(array);
                const rand = Math.floor(Math.random() * len.length);
                for (let l = 0; l < len.length; l++) {
                    if (l == rand) {
                        return array[len[l]];
                    }
                }
            } else {
                const rand = Math.floor(Math.random() * array.length);
                for (let l = 0; l < array.length; l++) {
                    if (l == rand) {
                        return array[l];
                    }
                }
            }
        }

const obj = {
  el1: 0,
  el2: 1,
  el3: 2,
  el4: 3,
  el5: 4,
  el6: 5,
  el7: 6,
  el8: 7,
  el9: 8,
  el10: 9
};

const arr = [
  0,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9
];

console.log('With Object\n',random_choice(obj, true));
console.log('Only array\n', random_choice(arr));
0

In Python it is...

import random

a=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'etc.']
print random.choice(a)
CoffeeRain
  • 4,460
  • 4
  • 31
  • 50