javascript 如何在一个范围内生成一个随机数但排除一些?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5520835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 17:27:58  来源:igfitidea点击:

How can I generate a random number within a range but exclude some?

javascriptrandomnumbers

提问by Pete

Basically I pick a random number between 0-24:

基本上我选择一个 0-24 之间的随机数:

Math.floor(Math.random() * myArray.length); // myArray contains 25 items

Lets say it comes out to be 8. Now I want to get another number in the same range 0-24 but this time, I do not want an 8. The next time, I might roll a 15. Now I want to roll again but I don't want an 8 or 15. The way I am handling this now is by using do while loops and if the number comes out the same, I just reroll.

假设结果是 8。现在我想得到 0-24 范围内的另一个数字,但这一次,我不想要 8。下一次,我可能会掷出 15。现在我想再掷一次但我不想要 8 或 15。我现在处理这个的方式是使用 do while 循环,如果数字相同,我就重新投掷。

This is a small portion of my homework and I, in fact, have it working to meet all the requirements so I guess you could say this is for my own personal benefit so I can write this properly and not end up on "the daily wtf".

这是我作业的一小部分,事实上,我让它可以满足所有要求,所以我想你可以说这是为了我个人的利益,所以我可以正确地写这篇文章,而不是最终成为“每日wtf ”。

回答by rockerest

Set an array with all the values (this is only a valid option if you're only doing small numbers, like the 25 in your example), like this:

设置一个包含所有值的数组(如果您只处理小数字,这只是一个有效选项,例如您示例中的 25),如下所示:

var array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24];

then, pick a random number between 0 and the array length:

然后,在 0 和数组长度之间选择一个随机数:

var num = Math.floor(Math.random() * array.length);

removethat index number from the array:

从数组中删除该索引号:

var roll = array.splice(num, 1);

Javascript splice()removes indexed items from an array and returns the item(s) as an array. Perfect for your use.

Javascript splice()从数组中删除索引项,并将项作为数组返回。非常适合您的使用。

Grab the first index from the roll, since we only cut 1 out anyway:

从卷中获取第一个索引,因为无论如何我们只删除了 1 个:

var yourNumber = roll[ 0 ];

Keep doing for as many rolls as you want. Also, you might want to store the original array as a copy so that you can "reset" the numbers easily.

继续做尽可能多的卷。此外,您可能希望将原始数组存储为副本,以便您可以轻松地“重置”数字。

回答by Alexander Mills

This is easy guys. You do not want recursion for this one. These answers are really bad. Ideally you do not want to hardcode the array, either.

这是容易的家伙。你不想递归这个。这些答案真的很糟糕。理想情况下,您也不希望对数组进行硬编码。

function getRandomWithOneExclusion(lengthOfArray,indexToExclude){

  var rand = null;  //an integer

    while(rand === null || rand === indexToExclude){
       rand = Math.round(Math.random() * (lengthOfArray - 1));
    }

  return rand;
}

now use the value returned from the above function to choose an element from whatever array you want, just like so:

现在使用从上面函数返回的值从你想要的任何数组中选择一个元素,就像这样:

var arr = [];
var random = getRandomWithOneExclusion(arr.length,5);  //array has length x, we want to exclude the 5th element
var elem = arr[random];

that's it. if you wanted to exclude more than value, then you would have to make this more sophisticated, but for excluding one value, this works well. A recursive solution for this is overkill and a bad idea.

而已。如果您想排除多个值,那么您必须使其更加复杂,但是对于排除一个值,这很有效。对此的递归解决方案是矫枉过正,而且是个坏主意。

I haven't tested this, but to exclude more than one element, try this:

我还没有测试过这个,但要排除多个元素,试试这个:

function getRandomWithManyExclusions(originalArray,arrayOfIndexesToExclude){

   var rand = null;

   while(rand === null || arrayOfIndexesToExclude.includes(rand)){
         rand = Math.round(Math.random() * (originalArray.length - 1));
    }
     return rand;
  }

The above method does not sound too different from the OP's original method. This method works properly because it does not sample in a biased way from the array.

上述方法听起来与 OP 的原始方法没有太大区别。此方法工作正常,因为它不会以有偏差的方式从数组中采样。

回答by Khez

Hmz :-? Fastest way to randomly get items from an array and ensure they're all unique would be:

嗯:-?从数组中随机获取项目并确保它们都是唯一的最快方法是:

var array = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24];

Array.prototype.shuffle = function shuffle(){
    var tempSlot;
    var randomNumber;
    for(var i =0; i != this.length; i++){
        randomNumber = Math.floor(Math.random() * this.length);
        tempSlot = this[i]; 
        this[i] = this[randomNumber]; 
        this[randomNumber] = tempSlot;
    }
}

while(array.length!=0){
    array.shuffle();
    alert(array.pop());    
}

回答by Salman A

Suppose you need to choose a random number from the range 1...5and exclude the values 2, 4then:

假设您需要从范围中选择一个随机数1...5并排除这些值,2, 4然后:

  • Pick a random number from the range 1...3
  • Sort excluded number list
  • For each excluded number less than/equal to the random number: add one to the random number
  • 从范围中选择一个随机数 1...3
  • 排序排除的号码列表
  • 对于每个小于/等于随机数的排除数:给随机数加一

function getRandomExcept(min, max, except) {
  except.sort(function(a, b) {
    return a - b;
  });
  var random = Math.floor(Math.random() * (max - min + 1 - except.length)) + min;
  var i;
  for (i = 0; i < except.length; i++) {
    if (except[i] > random) {
      break;
    }
    random++;
  }
  return random;
}

/*
 * Test iterations. Make sure that:
 * excluded numbers are skipped 
 * numbers are equally distributed
 */
(function(min, max, except) {
  var iterations = 1000000;
  var i;
  var random;
  var results = {};
  for (i = 0; i < iterations; i++) {
    random = getRandomExcept(min, max, except);
    results[random] = (results[random] || 0) + 1;
  }
  for (random in results) {
    console.log("value: " + random + ", count: " + results[random] + ", percent: " + results[random] * 100 / iterations + "%");
  }
})(1, 5, [2, 4]);

回答by Sebastian Umiński

This is example without recursion and without creating a huge array:

这是一个没有递归并且没有创建一个巨大数组的例子:

const getRandomWithExclude = (min, max, excludeArray) => {
  const randomNumber = Math.floor(Math.random() * (max - min + 1 - excludeArray.length)) + min;
  return randomNumber + excludeArray.sort((a, b) => a - b).reduce((acc, element) => { return randomNumber >= element - acc ? acc + 1 : acc}, 0);
}

const min = 1;
const max = 10;
const excludeArray = [8,2,5];
const result = getRandomWithExclude(min, max, excludeArray);

回答by reiver

Here is a tested and simple solution:

这是一个经过测试的简单解决方案:

var array= [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24];
var random_value; 
var index;
var shuffled_array = new Array(24);

for (var i = 0; i < 24; i++) { 
random_value = array[Math.floor(Math.random()*array.length)]; //Returns a value between 1 and 24
index = array.indexOf(random_card); //Gets the index of the choosen random value
array.splice(index, 1); //Go to index of that array and remove it
shuffled_array [i] = random_value; //Put that value in a new array

window.alert("array: "+array+"\n"+"random_value: "+random_value+"\n"+"shuffled_array: "+shuffled_array);
}

In other solutions i believe they forgot to search for the index.

在其他解决方案中,我相信他们忘记了搜索索引。

回答by theproxy

I'm sure there are a few ways to do this, but you could put all the numbers into something like a stack, jumble it all up and then pop off of it to get your random numbers. Or, randomly seek into it every time and remove it from the stack.

我敢肯定有几种方法可以做到这一点,但您可以将所有数字放入类似堆栈的东西中,将其全部混合,然后从中弹出以获得随机数。或者,每次随机查找它并将其从堆栈中删除。

回答by Sourav

step 1> create an array CHECK_ARRAY fill the array with value which is out of the range of your random number [fill it with 26 if you want to generate number within 0-25]

步骤 1> 创建一个数组 CHECK_ARRAY 用超出随机数范围的值填充数组[如果要生成 0-25 之间的数字,则用 26 填充]

step2-> generate a random number and add it to RANDOM_ARRAY and also add it to the CHECK_ARRAY that is

step2-> 生成一个随机数并将其添加到 RANDOM_ARRAY 并将其添加到 CHECK_ARRAY 中

i=0;
CHECK_ARRAY[i]=random;
i++;

step3-> generate a new random number and go though the CHECK_ARRAY, if you found 26 then ignore, else if you found duplicate then re-generate a random number and continue step 3 again until you found an unique random number !

step3->生成一个新的随机数并通过CHECK_ARRAY,如果找到26则忽略,否则如果发现重复则重新生成一个随机数并再次继续第3步,直到找到一个唯一的随机数!

回答by Heitor Giacomini

<div id="number" style="color: red; margin-left: 200px;">array</div>
<div id="arr" style="color: red; margin-left: 200px;">length</div>
<script>
  var arrayOfIndexesToExclude = new Array();
  function getRandomWithManyExclusions(){
    var rand = null;
      
     do{
       rand = Math.round(Math.random() * ( 9));
       if(arrayOfIndexesToExclude.length >= 10){
        arrayOfIndexesToExclude.length = 0;       
       }
    }while(arrayOfIndexesToExclude.includes(rand));
   
   arrayOfIndexesToExclude.push(rand);  
    
    document.getElementById("number").innerHTML = arrayOfIndexesToExclude;
    document.getElementById("arr").innerHTML = arrayOfIndexesToExclude.length;
  }
</script>