JS中生成不重复随机数

2024-01-02

我有以下功能

function randomNum(max, used){
 newNum = Math.floor(Math.random() * max + 1);

  if($.inArray(newNum, used) === -1){
   console.log(newNum + " is not in array");
   return newNum;

  }else{
   return randomNum(max,used);
  }
}

基本上,我创建一个 1 - 10 之间的随机数,并通过将其添加到数组中并检查新创建的数字来检查该数字是否已创建。我通过将其添加到变量来调用它。

UPDATED:
for(var i=0;i < 10;i++){

   randNum = randomNum(10, usedNums);
   usedNums.push(randNum);

   //do something with ranNum
}

这可行,但在 Chrome 中我收到以下错误:

Uncaught RangeError: Maximum call stack size exceeded

我猜这是因为我在其内部调用该函数太多次。这意味着我的代码不好。

有人可以帮我理清逻辑吗?确保我的号码不重复的最佳方法是什么?


如果我理解正确的话,那么您只是在寻找数字 1-10 的排列(即随机的、没有重复的数字)? 也许尝试在开始时生成这些数字的随机列表一次,然后按照自己的方式处理这些数字?

这将计算中数字的随机排列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);
}

因此,举例来说,如果您正在寻找 1 - 20 之间且也是偶数的随机数,那么您可以使用:

nums = [2,4,6,8,10,12,14,16,18,20];

然后通读一下ranNums为了回忆随机数。

正如您在方法中发现的那样,这不会带来花费越来越长的时间来查找未使用的号码的风险。

EDIT: 看完之后this http://bost.ocks.org/mike/shuffle/并运行测试jsperf http://jsperf.com/shuffles,看起来更好的方法是 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]);

基本上,通过避免使用“昂贵”的数组操作来提高效率。

奖金编辑: 另一种可能性是使用发电机 http://davidwalsh.name/es6-generators(假设你有support http://kangax.github.io/compat-table/es6/#generators):

function* shuffle(array) {

    var i = array.length;

    while (i--) {
        yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
    }

}

然后使用:

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最终将评估为undefined一旦你遍历完打乱数组中的所有元素。

总的来说,这不会像费舍尔-耶茨洗牌那么有效,因为你仍然splice-ing 一个数组。但不同之处在于,您现在仅在需要时才执行该工作,而不是预先完成所有工作,因此根据您的用例,这可能会更好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JS中生成不重复随机数 的相关文章

随机推荐