6

How would I select a random value (0 to 30) that is not in this array?

var list = new Array(1,3,4,7,8,9);
1
  • My question was slightly open ended, and I apologize. I am looking for different options, leads. Commented Aug 8, 2011 at 8:24

8 Answers 8

8

Build the complementary array and pick random values from it.

var list2 = new Array();
for(var i=0; i<30; i++)
  if(!list.contains(i))
    list2.push(i);

Then:

var rand = list2[Math.floor(Math.random() * list2.length)];
Sign up to request clarification or add additional context in comments.

Comments

3

A little recursive function:

getNum() {
  let randomNum = Math.floor(Math.random() * (30 - 1)) + 1
  if (list.includes(randomNum)) {
    return getNum()
  }
   return randomNum
}

Might be a little faster, since it first tries to return a random number, and then checks if it's in the array.

2 Comments

What is the performance like as the number of elements in the exclusion array grows? How does this strategy perform when the possible range grows from 30 to 30,000, and then to 30,000,000?
Thanks for asking, ran some tests. Used increasing arrays of random numbers and compared recursion to @slaphappy's complementary arr (most voted solution). Parameters(how many generated / how many in array): (1 in 1000) Recursion ~ 0.015ms / Complementary: ~ 1.25, 1.26 ms (1 in 10000) Rec ~ 0.030ms / Com ~ 115ms (1 in 100.000) Rec ~ 0.44ms / Com ~ 11573ms (or crash) (1000 in 1000) Rec ~ 4 ms / Com ~ 1182 ms (10.000 in 10.000) Rec ~ 317ms / Com ~ crash (1000.000 in 1000.000) Rec ~ 31422ms / Com ~ no way Note that recursion can sometimes double its runtime (when it calls itself)!
2
function RandomValueNotInArray(array)
{
    var e;
    do
    {
        e = Math.random() * 31; // n + 1
    } while (array.contains(e))
    return e;
}

3 Comments

but Math.random will generate float and It should be Math.random()*31?
The code speaks for itself, but for the sake of completeness consider adding a description
Math.random() returns a decimal value. You need to either Math.trunc() or Math.floor() the return value before comparing it to a list of integers, otherwise it will never match.
1

Assuming your list is reasonable small in size, create a list of numbers that are not in the array and then select a number from that array at random.

Comments

1

You need a while loop that tests if rand is in your restricted array and, if so, re-generate a new random number:

var rand;
do {
    rand = Math.floor(Math.random() * 31); // re-randomize, 0 to 30 inclusive
} while ($.inArray(rand, restricted) > -1);
return rand;

http://jsfiddle.net/mblase75/dAN8R/

Don't want jQuery? You can replace $.inArray(rand, restricted) with restricted.indexOf(rand) if you use this polyfill for old browsers.

2 Comments

Isn't this same as this answer stackoverflow.com/a/6979340/2333214 posted almost 2 years before this..
@TJ It might be, if array.contains() was a built-in method or Math.random() * 31 wasn't a floating-point number.
0

I would probably make an array or linked list from which I would subtract the unwanted items. That way I could keep removing items and just randomly select items from position 0 to the array's length - 1 without having to select the same thing twice.

Another way of doing it is to randomize a number between 0 and 30 and to keep doing it while it is found in the array. The only problems with that is knowing when the array is full (to get rid of infinite loops) and that it is a whole lot more processor intensive.

Comments

0

you can use filter .

var filteredArray = list.filter(function(e){
  return e!= Math.floor(Math.random() * (31));

});

1 Comment

Your code will create a list containing some numbers that are present in the array. The OP wants something quite opposite, only a single number not in the array.
-1

PHP in 2 lines:

$result = array_diff(range(1,30), array(1,3,4,7,8,9)); 
echo $result[array_rand($result)];

2 Comments

If this question was tagged as PHP before, it isn't now.
Just trying to help people arriving here from Google.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.