javascript - JS中生成不重复随机数

标签 javascript jquery

我有以下功能

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 即可记忆起随机数。

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

编辑:阅读后this并在 jsperf 上运行测试,看起来更好的方法是 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]);

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

额外编辑:另一种可能性是使用 generators (假设您有 support ):

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.

一旦您遍历完打乱数组中的所有元素,ranNums.next().value 最终将计算为 undefined

总体而言,这不会像 Fisher–Yates Shuffle 那样高效,因为您仍在拼接数组。但不同之处在于,您现在仅在需要时才执行该工作,而不是预先完成所有工作,因此根据您的用例,这可能会更好。

关于javascript - JS中生成不重复随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45037458/

相关文章:

javascript - 在 AngularJS 中初始化 select2

javascript - 有时会隐藏一个按钮,使两个按钮居中

javascript - 返回未定义的 ajax 函数

jquery - 在 Safari 和 Chrome 中摇动 css 转换

javascript - D3.JS如何删除/更新

javascript - 如何在此选择列表中添加图像? Javascript?

javascript - 有没有自动下载图像的javascript答案?

php - 使用 onclick 使用 jquery 或 javascript 创建 session 变量?

javascript - node scripts/install.js 没有指向正确的正确 url

javascript - 移动太慢时 jquery mouseleave 问题