Randomize value in Javascript

2019-04-14 15:43发布

问题:

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);

回答1:

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;
    };
}());


回答2:

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]);


回答3:

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.



回答4:

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.



回答5:

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.



回答6:

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;


回答7:

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!



回答8:

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) );