生成1到100之间的唯一随机数

dot*_*tty 87 javascript random integer numbers

如何使用JavaScript生成8个,比如1到100之间的唯一随机数?

ada*_*101 138

var arr = [];
while(arr.length < 8){
    var r = Math.floor(Math.random() * 100) + 1;
    if(arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);
Run Code Online (Sandbox Code Playgroud)

  • 哇.天真似乎有点强烈.它可能不是最好的解决方案,但它简单,简单,易于查看正在发生的事情,并且在可接受的操作参数范围内运行以满足需要完成的任务.接下来的任务.完美是伟大的,但'完成'比'完美'更好. (32认同)
  • 对于这些问题,实际代码比伪代码好得多;)(删除了我的答案,即伪代码...) (12认同)
  • -1:这种算法是天真的方法; 这是非常低效的. (6认同)
  • 函数有可能在数组中返回0.根据以下链接:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random,Math.random()`返回0(含)与1之间的随机数(不包括)`.如果`Math.random()`意外返回0,那么`Math.ceil(0)`也是0,尽管机会很低. (4认同)
  • O可以被选中; 使用var randomnumber = Math.ceil(Math.random()*100) (3认同)
  • @Alsciende不会取决于被挑选的数字与选择数字的比率吗?例如,如果从1到1,000,000中挑选8个数字,我会认为这会更好.如果从1到1,000,000中选择800,000个数字,那么Knuth Shuffle会更适合. (2认同)
  • @Frerich:虽然我发现一些效率低下(`for` 循环可以替换为 `i=arr.length; while (i--)`),但我对你的解决方案很感兴趣。 (2认同)

Яeg*_*ght 37

  1. 使用数字1到100填充数组.
  2. 洗牌吧.
  3. 获取结果数组的前8个元素.

  • 当然,调整代码只进行前8次洗牌会更有效率吗?(然后采用半混乱数组的最后8个元素) (7认同)
  • 如果 N=10^12 怎么办?效率不高。 (2认同)
  • 在现实世界中,@ shinzou不会使用JavaScript对10 ^ 12的数字进行排序。一个关于问题的问题需要一个简单的答案。我不是在这里解决世界饥饿问题。我有足够的能力做到这一点,但这不是问题所在。 (2认同)

ngf*_*ixl 17

另一种方法是生成一个 100 项的数组,并随机排序。这实际上导致了一个非常短且(在我看来)简单的片段。

const numbers = Array(100).fill().map((_, index) => index + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));
Run Code Online (Sandbox Code Playgroud)


Pra*_*are 13

生成100个数字的排列,然后连续选择.

使用Knuth Shuffle(又名Fisher-Yates shuffle)算法.

JavaScript的:

  function fisherYates ( myArray,stop_count ) {
  var i = myArray.length;
  if ( i == 0 ) return false;
  int c = 0;
  while ( --i ) {
     var j = Math.floor( Math.random() * ( i + 1 ) );
     var tempi = myArray[i];
     var tempj = myArray[j];
     myArray[i] = tempj;
     myArray[j] = tempi;

     // Edited thanks to Frerich Raabe
     c++;
     if(c == stop_count)return;

   }
}
Run Code Online (Sandbox Code Playgroud)

代码从链接中复制.

编辑:

改进代码:

function fisherYates(myArray,nb_picks)
{
    for (i = myArray.length-1; i > 1  ; i--)
    {
        var r = Math.floor(Math.random()*i);
        var t = myArray[i];
        myArray[i] = myArray[r];
        myArray[r] = t;
    }

    return myArray.slice(0,nb_picks);
}
Run Code Online (Sandbox Code Playgroud)

潜在问题:

假设我们有100个数字的数组{例如[1,2,3 ... 100]},我们在8次交换后停止交换; 然后大多数时候阵列看起来像{1,2,3,76,5,6,7,8,......这里的数字将被洗牌...... 10}.

因为每个数字将以1/100的概率交换,所以概率.交换前8个数字是8/100而prob.交换其他92的是92/100.

但是如果我们运行完整数组的算法,那么我们肯定(几乎)每个条目都被交换.

否则我们会面临一个问题:选择哪8个数字?

  • 这种方法是正确的但不是最理想的:你可以在八次交换后停止洗牌,因为你只需要八个随机数.上面的代码交换整个数组(在这种情况下,100个元素). (5认同)

Vic*_*inn 10

如果你想避免一个库,上面的技术很好,但是如果你对一个库有好处,我会建议你查看Chance在JavaScript中生成随机内容.

专门解决您的问题,使用Chance就像以下一样简单:

// One line!
var uniques = chance.unique(chance.natural, 8, {min: 1, max: 100});

// Print it out to the document for this snippet so we can see it in action
document.write(JSON.stringify(uniques));
Run Code Online (Sandbox Code Playgroud)
<script src="http://chancejs.com/chance.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

免责声明,作为Chance的作者,我有点偏颇;)


bel*_*bob 8

为了避免任何漫长而不可靠的洗牌,我会做以下事情......

  1. 按顺序生成包含1到100之间的数字的数组.
  2. 生成1到100之间的随机数
  3. 在数组中查找此索引处的数字并存储在结果中
  4. 从阵列中删除elemnt,使其缩短一个
  5. 从步骤2开始重复,但使用99作为随机数的上限
  6. 从步骤2开始重复,但使用98作为随机数的上限
  7. 从步骤2开始重复,但使用97作为随机数的上限
  8. 从步骤2开始重复,但使用96作为随机数的上限
  9. 从步骤2开始重复,但使用95作为随机数的上限
  10. 从步骤2开始重复,但使用94作为随机数的上限
  11. 从步骤2开始重复,但使用93作为随机数的上限

瞧 - 没有重复的数字.

如果有人感兴趣,我可以稍后发布一些实际代码.

编辑:这可能是我的竞争对手,但是,看过@Alsciende的帖子后,我无法抗拒发布我承诺的代码.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>8 unique random number between 1 and 100</title>
<script type="text/javascript" language="Javascript">
    function pick(n, min, max){
        var values = [], i = max;
        while(i >= min) values.push(i--);
        var results = [];
        var maxIndex = max;
        for(i=1; i <= n; i++){
            maxIndex--;
            var index = Math.floor(maxIndex * Math.random());
            results.push(values[index]);
            values[index] = values[maxIndex];
        }
        return results;
    }
    function go(){
        var running = true;
        do{
            if(!confirm(pick(8, 1, 100).sort(function(a,b){return a - b;}))){
                running = false;
            }
        }while(running)
    }
</script>
</head>

<body>
    <h1>8 unique random number between 1 and 100</h1>
    <p><button onclick="go()">Click me</button> to start generating numbers.</p>
    <p>When the numbers appear, click OK to generate another set, or Cancel to stop.</p>
</body>
Run Code Online (Sandbox Code Playgroud)


Ali*_*ter 7

使用Set的现代JS解决方案(以及平均情况O(n))

const nums = new Set();
while(nums.size !== 8) {
  nums.add(Math.floor(Math.random() * 100) + 1);
}

console.log([...nums]);
Run Code Online (Sandbox Code Playgroud)