If I understand right then you're just looking for a permutation (i.e. the numbers randomised with no repeats) of the numbers 1-10? Maybe try generating a randomised list of those numbers, once, at the start, and then just working your way through those?
This will calculate a random permutation of the numbers in nums:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
So, for example, if you were looking for random numbers between 1 - 20 that were also even, then you could use:
nums = [2,4,6,8,10,12,14,16,18,20];
Then just read through ranNums in order to recall the random numbers.
This runs no risk of it taking increasingly longer to find unused numbers, as you were finding in your approach.
EDIT: After reading this and running a test on jsperf, it seems like a much better way of doing this is a Fisher–Yates Shuffle:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
Basically, it's more efficient by avoiding the use of 'expensive' array operations.
BONUS EDIT: Another possibility is using generators (assuming you have support):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
Then to use:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
where ranNums.next().value will eventually evaluate to undefined once you've run through all the elements in the shuffled array.
Overall this won't be as efficient as the Fisher–Yates Shuffle because you're still splice-ing an array. But the difference is that you're now doing that work only when you need it rather than doing it all upfront, so depending upon your use case, this might be better.
If I understand right then you're just looking for a permutation (i.e. the numbers randomised with no repeats) of the numbers 1-10? Maybe try generating a randomised list of those numbers, once, at the start, and then just working your way through those?
This will calculate a random permutation of the numbers in nums:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
So, for example, if you were looking for random numbers between 1 - 20 that were also even, then you could use:
nums = [2,4,6,8,10,12,14,16,18,20];
Then just read through ranNums in order to recall the random numbers.
This runs no risk of it taking increasingly longer to find unused numbers, as you were finding in your approach.
EDIT: After reading this and running a test on jsperf, it seems like a much better way of doing this is a Fisher–Yates Shuffle:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
Basically, it's more efficient by avoiding the use of 'expensive' array operations.
BONUS EDIT: Another possibility is using generators (assuming you have support):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
Then to use:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
where ranNums.next().value will eventually evaluate to undefined once you've run through all the elements in the shuffled array.
Overall this won't be as efficient as the Fisher–Yates Shuffle because you're still splice-ing an array. But the difference is that you're now doing that work only when you need it rather than doing it all upfront, so depending upon your use case, this might be better.
//random number without repetition in JavaScript, Just in one line;
//it can be used as _id;
//it not need to store or check;
const myRnId = () => parseInt(Date.now() * Math.random());
console.log(myRnId()); // any random number included timeStamp;
create random numbers with out them repeating in javascript
Generate Non-Repeating Random Number From A Set - JavaScript - SitePoint Forums | Web Development & Design Community
javascript - Prevent repetitive random numbers - Code Review Stack Exchange
Random number generator without dupes in Javascript? - Stack Overflow
Videos
Generate a range of numbers:
var numbers = [1, 2, 3, 4];
And then shuffle it:
function shuffle(o) {
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
var random = shuffle(numbers);
One more way to do it:
for (var a = [0, 1, 2, 3, 4], i = a.length; i--; ) {
var random = a.splice(Math.floor(Math.random() * (i + 1)), 1)[0];
console.log(random);
}
Don't know if it's even possible to make it more compact.
Tests: http://jsfiddle.net/2m3mS/1/
Here is embed demo:
$('button').click(function() {
$('.output').empty();
for (var a = [0, 1, 2, 3, 4], i = a.length; i--; ) {
var random = a.splice(Math.floor(Math.random() * (i + 1)), 1)[0];
$('.output').append('<span>' + random + '</span>');
}
}).click();
.output span {
display: inline-block;
background: #DDD;
padding: 5px;
margin: 5px;
width: 20px;
height: 20px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="output"></div>
<button>Run</button>
In practice, your code will be fine. In theory, it is not guaranteed to terminate, but the probability of that happening is literally negligible.
However, what you are doing is picking a random integer between 1 and 3 (both inclusive), with the number not repeating. With only three possibilities, we could draw up a state machine:
states = {
1: [2, 3],
2: [1, 3],
3: [1, 2] };
if (lastRandom === undefined) {
random = Math.floor(Math.random() * 3) + 1;
}
else {
random = states[lastRandom][Math.floor(Math.random() * 2)];
}
lastRandom = random;
Unfortunately, that involves generating all the states first, which is impractical for larger ranges. There, we could use this more clever approach:
var min = 1;
var max = 3;
if (lastRandom === undefined) {
random = Math.floor(Math.random() * (max - min + 1)) + min;
}
else {
random = Math.floor(Math.random() * (max - min )) + min;
if (random >= lastRandom) random += 1;
}
lastRandom = random;
So if we are choosing the first number, everything works as usual. But for any subsequent number, we choose an integer from a set one smaller (to reflect that one number, the lastRandom, can't be chosen). If the random number obtained like this is less than the lastRandom, it can be used as is. Otherwise it has to be incremented by one, so that the lastRandom has been skipped.
Test to compare code:

You can do this without checking what the previous selection was. On the first iteration, you select a number from 1 to n, call this r. However, subsequent iterations should select a number from 1 to (n - 1), call this rn. The next random number in the sequence is then ((r-1 + nr) % n) + 1
It works like this: imagine the numbers 1:n are stored in array. If you start at some position x, you get to the next position x, but not back to x, by adding n-1 to x (but not going past the nth index by starting over at the beginning when you pass it, hence the modulus operation). That's kind of hard to visualize without a diagram and i'm not good at making internet forum diagrams.
var nums = [1,2,3,4,5,6,7,8,9,10,11,12];
var gen_nums = [];
function in_array(array, el) {
for(var i = 0 ; i < array.length; i++)
if(array[i] == el) return true;
return false;
}
function get_rand(array) {
var rand = array[Math.floor(Math.random()*array.length)];
if(!in_array(gen_nums, rand)) {
gen_nums.push(rand);
return rand;
}
return get_rand(array);
}
for(var i = 0; i < 9; i++) {
console.log(get_rand(nums));
}
The most effective and efficient way to do this is to shuffle your numbers then print the first nine of them. Use a good shuffle algorithm.What Thilo suggested will give you poor results. See here.
Edit Here's a brief Knuth Shuffle algorithm example:
void shuffle(vector<int> nums)
{
for (int i = nums.size()-1; i >= 0; i--)
{
// this line is really shorthand, but gets the point across, I hope.
swap(nums[i],nums[rand()%i]);
}
}
use a variable to check if the number is the same.
something like this: (using LastNumber to store the lastNumber) if it allready is used we gonna try again)
var videoLinks = [
....
];
var lastNumber = 0;
var randomNumber = function () {
var getRandomNumber = Math.floor(Math.random() * 5);
if(getRandomNumber != lastNumber){
var random = videoLinks[getRandomNumber];
document.getElementById("videoWrapper").innerHTML = random[0];
lastNumber = getRandomNumber;
}else{
randomNumber();
}
};
randomNumber(); // To call the function on load
You can create an array to keep the exiting generated numbers.
var existingNumbers = [];
var maxNumbers = 5;
var randomNumber = function() {
if (existingNumbers.length != maxNumbers) {
do {
getRandomNumber = Math.floor(Math.random() * maxNumbers);
} while (existingNumbers.indexOf(getRandomNumber) > -1);
existingNumbers.push(getRandomNumber);
var random = videoLinks[getRandomNumber]
document.getElementById("videoWrapper").innerHTML = random[0];
}
};
There are a number of ways you could achieve this.
Solution A: If the range of numbers isn't large (let's say less than 10), you could just keep track of the numbers you've already generated. Then if you generate a duplicate, discard it and generate another number.
Solution B:
Pre-generate the random numbers, store them into an array and then go through the array. You could accomplish this by taking the numbers 1,2,...,n and then shuffle them.
shuffle = function(o) {
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
var randorder = shuffle([0,1,2,3,4,5,6]);
var index = 0;
setInterval(function() {
$('.foo:nth-of-type('+(randorder[index++])+')').fadeIn(300);
}, 300);
Solution C: Keep track of the numbers available in an array. Randomly pick a number. Remove number from said array.
var randnums = [0,1,2,3,4,5,6];
setInterval(function() {
var m = Math.floor(Math.random()*randnums.length);
$('.foo:nth-of-type('+(randnums[m])+')').fadeIn(300);
randnums = randnums.splice(m,1);
}, 300);
You seem to want a non-repeating random number from 0 to 6, so similar to tskuzzy's answer:
var getRand = (function() {
var nums = [0, 1, 2, 3, 4, 5, 6];
var current = [];
function rand(n) {
return (Math.random() * n) | 0;
}
return function() {
if (!current.length) current = nums.slice();
return current.splice(rand(current.length), 1)[0];
}
}());
// Run 3 times
for (let i=0; i<3; i++) {
console.log('run ' + i);
for (let j=0; j<7; j++) {
console.log(getRand());
}
}
It will return the numbers 0 to 6 in random order. When each has been drawn once, it will start again.
When creating a random number, only use one that isn't yet in your array:
var number = [];
for(i= 0; i <= 5; i++){
var num;
while ( number.includes( num = Math.floor(Math.random()*40) ) );
number[i] = num;
}
console.log(number);
The empty while loop repeatedly selects a number until it finds one that isn't in the number array. Only after that successfully finishes does it then add that number to the array.
random() function generates number randomly so there is a possibility that one number can occur again. To avoid that once a new number is generated by random() function you can check whether this number is already present in your array or not. Add it to your array only if it is not already present. A working snippet is provided below:
function generatenumbers(){
var number = new Array();
var i=0;
while(i<6){
var val = Math.floor(Math.random()*40);
if(number.includes(val) === false){
number.push(val);
i++;
}
}
document.getElementById("generated").innerHTML = "";
i = 0;
for(i=0; i<= number.length - 1; i++){
let node = document.createElement("LI");
let txt = document.createTextNode(number[i]);
node.appendChild(txt);
document.getElementById("generated").appendChild(node);
}
}