run for random numbers and keep state [duplicate]

我的梦境 提交于 2019-12-17 13:26:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!