【问题标题】:Generating random number in Array without repeatition - JavaScript在不重复的数组中生成随机数 - JavaScript
【发布时间】:2014-04-25 23:47:00
【问题描述】:

所以我知道这个任务已经被问过了,但是所有给出的答案我都已经知道了。我不想为所有可能的数字制作一个变量(这始终是答案)。所以要回答这个问题,我想制作一个随机数生成器,它会生成 7 个数字,它们一定不一样。例如,我得到随机数: "5,16,12,5,21,37,2" ...但我不想再次使用数字5,所以我想要不同的数字。我为一代做了一个代码,但我想不出任何好的方法/方法来做到这一点。我在想也许检查数字是否已经在数组中,如果是,则生成另一个数字,但由于我是 JavaScript 的业余爱好者,我不知道该怎么做。所以这是我的 JavaScript 代码:

// JavaScript 文档

function TableOn()
{
    document.write("<table border='1'>");
}
function TableOff()
{
    document.write("</table>");
}

function RandNum()
{
    var n = new Array();
    for(var i=0;i<7;i++)
    {
        n[i] = Math.round((1+(Math.random()*40)));
    }
    TableOn();
    for(var c=0;c<7;c=c+1)
    {
        document.write("<tr><td>"+n[c]+"</td></tr>");
    }
    TableOff();
}

在 HTML 中,我只有一个按钮,即 onclick="RandNum()" ... 请原谅我的英语。

【问题讨论】:

  • 为什么你不想枚举所有可能的值然后随机播放它们?如果您有与该方法相冲突的要求,没关系,但您必须解释它们,否则我们不知道真正的问题是什么。
  • 我只是不想使用这种方法。如果我想要 7 个数字,最多可以达到 1000 个怎么办...继续写 1000 个数字...我相信这可以通过其他方式完成...
  • 随心所欲,但如果你使用“检查重复”的方法并且值的范围接近值的数量,性能会很糟糕。

标签: javascript html arrays random


【解决方案1】:
    var n = new Array(),num;
function TableOn()
{
    document.write("<table border='1'>");
}
function TableOff()
{
    document.write("</table>");
}
function check_repition()
{
num=Math.round((1+(Math.random()*40)))
if(n.indexOf(num)==-1)
return true;
else 
return false;
}

 function RandNum()
    {

        for(var i=0;i<7;i++)
        {
if(check_repition())
            n[i] =num;
else // keep checking
{
    check_repition()
     n[i] =num;
}
        }
        TableOn();
        for(var c=0;c<7;c=c+1)
        {
            document.write("<tr><td>"+n[c]+"</td></tr>");
        }
        TableOff();
    }
    RandNum()

【讨论】:

  • @Pointy 抱歉在发布修复我的错误之前没有检查,现在应该可以了。
【解决方案2】:

不确定是否真的需要 OP 的非重复要求,但如果您的数字范围不太大,这里有一些可行的方法:

http://jsfiddle.net/6rEDV/1/

function range(start, end, step) {
    if (typeof step === 'undefined') {
        step = 1;
    }

    if (typeof start === 'undefined' || typeof end === 'undefined') {
        throw TypeError('Must have start and end');
    }

    var ret = [];
    for (var i = start; i <= end; i += step) {
        ret.push(i);
    }

    return ret;
};

// source: http://stackoverflow.com/a/6274381/520857
function shuffle(o) { //v1.0
    for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
};

function getNonRepeatingRand(min, max, num) {
    var arr = shuffle(range(min, max));
    return arr.slice(0, num-1);
}

// Get 7 random numbers between and including 1 and 1000 that will *not* repeat
console.log(getNonRepeatingRand(1,1000,7));

一种可能较慢但占用内存较少的方法:

http://jsfiddle.net/Qnd8Q/

function rand(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function getNonRepeatingRand(min, max, num) {
    var ret = [];

    for (var i = 0; i < num; i++) {
        var n = rand(min, max);
        if (ret.indexOf(n) == -1) {
            ret.push(n);
        } else {
            i--;
        }
    }
    return ret;
}

console.log(getNonRepeatingRand(1,5,5));

【讨论】:

    【解决方案3】:

    这是一个在[min, max)中生成n个不重复随机数数组的函数:

    function rands(n, min, max) {
      var range = max - min;
      if (range < n)
        throw new RangeError("Specified number range smaller than count requested");
    
      function shuffle() {
        var deck = [], p, t;
        for (var i = 0; i < range; ++i)
          deck[i] = i + min;
    
        for (i = range - 1; i > 0; --i) {
          p = Math.floor(Math.random() * i);
          t = deck[i];
          deck[i] = deck[p];
          deck[p] = t;
        }
        return deck.slice(0, n);
      }
    
      function find() {
        var used = {}, rv = [], r;
        while (rv.length < n) {
          r = Math.floor(Math.random() * range + min);
          if (!used[r]) {
            used[r] = true;
            rv.push(r);
          }
        }
        return rv;
      }
    
      return range < 3 * n ? shuffle() : find();
    }
    

    此代码检查可能值的范围并将其与请求的随机值的数量进行比较。如果范围小于请求值数量的三倍,则代码使用 shuffle 来避免查找方法的糟糕性能。但是,如果范围很大,则使用查找方法。

    【讨论】:

      【解决方案4】:

      我会使用一个字符串,用一个分隔符存储生成的随机数。然后检查新生成的数字是否在该字符串中。

      类似的东西

      generated = "";
      for(var i=0;i<7;i++)
      {
          generate = Math.round((1+(Math.random()*40))); //generate = 5
          while (generated.indexOf("[" + generate + "]") != -1) { //checking if the [5] is already in the generated string, and loop until it's a different number
              generate = Math.round((1+(Math.random()*40))); //get a new random number
          }
          generated += "[" + generate + "]";
          n[i] = generate;
      }
      

      或者你可以采取另一种更长的方法

      for(var i=0;i<7;i++)
      {
          repeated = true;
          while (repeated) { 
              repeated = false;
              generate = Math.round((1+(Math.random()*40)));
              for (var a=0; a < i, a++) {
                  if (generate == n[a]) { repeated = true; }
              }
          }
          n[i] = generate;
      }
      

      【讨论】:

        【解决方案5】:

        我会这样做:

        var nums = [], numsLen = 5, maxNum = 100, num;
        while (nums.length < numsLen) {
            num = Math.round(Math.random() * maxNum);
            if (nums.indexOf(num) === -1) {
                nums.push(num);
            }
        }
        

        这会生成一个包含 0..100 范围内的 5 个随机数的数组。 (numsLen 不能大于 maxNum。)

        【讨论】:

        • 这是一个通常非常糟糕的算法。将numsLen 移动到100 的次数越多,平均运行时间就会爆炸。
        • 谢谢,这就是我想要的! :)
        • @IngoBürk:当然,这不适用于大数组。但对于小型阵列,这是一个干净简单的解决方案。
        • 我的答案包含您的答案作为我的答案的一部分,我还提供了一种替代方法,它以较低的复杂性但更高的内存使用率运行。还把它们做成函数,以便灵活使用:)
        • 使用.indexOf()而不是维护一个“地图”对象会使这比其他方式更慢。
        【解决方案6】:

        这些命令可用于检查一个值是否在您的数组中:

        if ( !!~n.indexOf(someVal) ) {
            // someVal is in array "n"
        }
        if ( !~n.indexOf(someVal) ) {
            // someVal is not in array "n"
        }
        

        【讨论】:

          猜你喜欢
          • 2019-09-22
          • 1970-01-01
          • 2016-05-05
          • 1970-01-01
          • 2011-12-28
          • 2021-03-31
          • 2012-05-28
          • 2012-06-01
          相关资源
          最近更新 更多