问题
I use the following code to get random value from specifed range
var provideRanges = function(){
var aa = [];
_.times(3, function(i) {
console.log(i);
let num = _.random(10, 20)
console.log("num = :" + num)
debugger;
aa.push(num);
console.log("value is :" + aa[i]);
});
}
This is working and provide array of 3 values between the specified range when you call to this function, but the problem here become more difficult when I need that if I call it again ignore exclude the previous provided number from the provided numbers (like if it provide 10,11,12 the next time those numbers should not be provided...), is there is nicer way to do it? I try to use recoursive call but get lost:( ,any idea how to do it?
回答1:
One approach would be to create an array to store existing selections, push selected elements to an array, check if the array contains the element and if the array storing values .length is greater than or equal to maximum range minus minimum range.
It is not clear from description at Question what should occur once all of the elements in the range have been returned?
var range = [10, 20];
var not = [];
function randomRange(range, n) {
if (not.length >= range[1] - range[0]) {
return "all numbers in range used"
}
var curr = [];
var res = [];
for (let i = range[0]; i < range[1]; i++) {
if (!not.some(function(num) {
return i == num
}) && not.length < range[1] - range[0]) {
curr.push(i)
}
}
for (let i = 0; i < n; i++) {
var j = curr.splice(Math.floor(Math.random() * curr.length), 1)[0];
res[i] = not[not.length] = j;
}
return res.filter(Boolean)
}
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
回答2:
My solution uses Set to retain the uniqueness of the values:
const getRangeRandomizer = ([min, max]) => { // create the range randomizer
const state = new Set(); // the numbers that were produced from the range
/** the returned method can be used to get more numbers from the range **/
return (numOfRandoms) => {
const discarded = new Set(); // this Set is used to count numbers that are not unique
const range = max - min + 1;
const result = [];
let i = 0;
let randNum;
while (i < numOfRandoms && discarded.size < range) { // if we added numOfRandoms times or we discarded delta optionsm the loop end - this prevents endless loops
randNum = Math.floor(Math.random() * (range) + min);
if (state.has(randNum)) {
discarded.add(randNum);
} else {
state.add(randNum);
result.push(randNum);
i++;
}
}
return result;
}
}
const provideRanges = getRangeRandomizer([10, 20]); // create a range randomizer
console.log(provideRanges(4));
console.log(provideRanges(3));
console.log(provideRanges(2));
console.log(provideRanges(4)); // only 2 results will be provided, because the rest were used
const provideOtherRanges = getRangeRandomizer([15, 20]); // create a range randomizer
console.log(provideOtherRanges(100));
回答3:
Here's a solution using lodash's sampleSize and pullAt:
// numbers = [10, 11, ... 19]
let numbers = _.range(10, 20);
// sampleSize will return an array containg the numbers randomized
let sample = _.sampleSize(numbers, numbers.length)
// get the first 3 numbers from the sample (pullAt will mutate sample)
let first3 = _.pullAt(sample, [0,1,2]);
// get the next 3 numbers etc.
let next3 = _.pullAt(sample, [0,1,2]);
let numbers = _.range(10, 20);
let sample = _.sampleSize(numbers, numbers.length)
let sample1 = _.pullAt(sample, [0,1,2]);
let sample2 = _.pullAt(sample, [0,1,2]);
let sample3 = _.pullAt(sample, [0,1,2]);
let sample4 = _.pullAt(sample, [0,1,2]);
console.log(sample1)
console.log(sample2)
console.log(sample3)
console.log(sample4)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
回答4:
You may do as follows
function RandomSomething(n,m){
this.choices = new Array(n).fill().map((_,i) => i+m);
}
RandomSomething.prototype.randomFromRange = function(){
return new Array(3).fill()
.map(function(r,i){
r = this.choices.length > 3 ? this.choices
.splice(Math.floor((Math.random()*this.choices.length)),1)[0]
: this.choices[i];
return r;
}.bind(this));
};
var obj = new RandomSomething(10,100); // generate randoms at range 100-109
console.log(JSON.stringify(obj.randomFromRange()));
console.log(JSON.stringify(obj.randomFromRange()));
console.log(JSON.stringify(obj.randomFromRange()));
console.log(JSON.stringify(obj.randomFromRange()));
console.log(JSON.stringify(obj.randomFromRange()));
来源:https://stackoverflow.com/questions/41001101/run-for-random-numbers-and-keep-state