I need to randomize set of values in JS, and I call function randomize for example three times. How can I remember and block random generator from giving me results that it gave me previous times? I can only give one value once.
var value = Math.floor(Math.random() * 11);
Use the memoization pattern.
var randomize = (function () {
var memo = [],
maxlen = 10;
return function() {
if (memo.length === maxlen) {
throw new Error('Out of values');
}
var value = Math.floor(Math.random() * (maxlen + 1));
if (memo.indexOf(value) !== -1) {
return randomize();
}
memo.push(value);
return value;
};
}());
Something like this (tested):
Array.prototype.unique = function () {
var r = new Array();
o:for(var i = 0, n = this.length; i < n; i++)
{
for(var x = 0, y = r.length; x < y; x++)
{
if(r[x]==this[i])
{
continue o;
}
}
r[r.length] = this[i];
}
return r;
}
var temp = [];
//keep going until the array size is three
while(temp.length < 3) {
temp.push(Math.floor(Math.random() * 11));
//unique() will remove the dupes thus affecting the length
temp = temp.unique();
}
alert(temp[0] + ' ' + temp[1] + ' ' + temp[2]);
What is your larger goal? If you're trying to select items from a finite set in a random order, then you'll want to look at using a shuffle algorithm to randomize the ordering and then remove them in the resulting shuffled order as needed.
Instead of using Random(), you can use time ticks which will give you a random value everytime you use them -
var random = (new Date()).getTime();
Or, you can extend the default JS Array
, and add the contains
method to it. Every random value you generate will be added to the array, but before adding, the contains
method will check whether it already exists in the array or not.
One of the wonderful randoms are provided by allocating sequential array of int:
for(i = 0; i < 100; ++i) myArr[i]=i;
And after it you shift numbers there in order Math.floor(Math.random() * myArr.length);
benefit of such approach - you get non-repeatable sequence of any length.
Just implement a pseudo random algorithm, with a random seed. There are several such algorithms, some are better than others. Wikipedia has a list of algorithms.
You could use the Linear Congruential Generator (LCG), one of the best known Pseudo Random Number Generator (PRNG). The following code uses the built inn random number generator (which probably uses the LCG), and then uses LCG algorithm for the other numbers. This makes sure no two consecutive numbers are the same. There are also a range and offset, so you can limit the range of numbers you get (in this case it would be numbers from 1 to 10).
var range = 9;
var offset = 1;
function rand(x){
var a = 1664525;
var m = 4294967296;
var c = 1013904223;
return (a*x + c) % m;
}
var num1 = rand(Math.round(Math.random()*100000)) % range + offset;
var num2 = rand(num1) % range + offset;
var num3 = rand(num2) % range + offset;
Judging from your comments, it sounds like you have a small range of values (i.e. from 1-10) which you want to randomly select your values from.
In that case your best bet is to store your values in an array and randomly splice them out.
I prefer to perform these kinds of operations using some sort of generator.
function createRandomGenerator( array ) {
return function() {
return array.splice(Math.floor(Math.random() * array.length ),1)[0];
}
}
To use the generator creator, provide it with your short list of unique values, and store the result. The result is a generator you can use to generate N number of random numbers from your list of unique values. (Where N is the length of the array you seeded your random generator with).
var random1to10 = createRandomGenerator( [1,2,3,4,5,6,7,8,9,10] );
You can then use the generator by calling the generator that that function returns over and over.
var a = [];
for( var i = 0; i < 10; i++ ) {
a.push( random1to10() );
}
alert(a.join(','));
If you do not have a pre-defined set of numbers you wish to use, I'd recommend Török Gábor's solution above.
Cheers!
Use a hash.
var values = {};
count = 0; //keep count of how many are there if you want.
while( count < something ) {
var rand = Math.random();
if( !values[rand] ) {
values[rand] = true;
count++;
}
}
Then you can dump all of those into an array if you want - that's O(n).
var arrValues = [];
for( var p in values ) arrValues.push( new Number(p) );