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

时间:2021-11-10 08:38:17

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》上。

8 个解决方案

#1


14  

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);

remove that 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:

从名单中选出第一个索引,因为我们只裁掉了一个:

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.

你想做多少卷就做多少卷。此外,您可能希望将原始数组存储为副本,以便可以轻松“重置”这些数字。

#2


3  

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的原始方法没有太大的不同。该方法工作正常,因为它没有从数组中以偏置的方式进行采样。

#3


2  

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

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

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());    
}

#4


0  

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.

我相信有几种方法可以做到这一点,但是你可以把所有的数字放到一个堆栈中,把它们都堆起来,然后弹出来,得到随机的数字。或者,每次都随机地搜索它,然后从堆栈中删除它。

#5


0  

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

>生成一个随机数并将其添加到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 !

>生成一个新的随机数并遍历CHECK_ARRAY,如果找到26,然后忽略,否则如果找到duplicate,则重新生成一个随机数,继续第三步,直到找到一个唯一的随机数!

#6


0  

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.

在其他的解决方案中,我认为他们忘记了搜索索引。

#7


0  

<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>

#8


0  

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

假设您需要从范围1中选择一个随机数……5并排除2、4的值:

  • Pick a random number from the range 1...3
  • 从范围1…3中选择一个随机数
  • Sort excluded number list
  • 这种排除列表数量
  • For each excluded number less than the random number: add one to the random number
  • 对于每个被排除的数字小于随机数:在随机数中增加一个

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]);

#1


14  

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);

remove that 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:

从名单中选出第一个索引,因为我们只裁掉了一个:

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.

你想做多少卷就做多少卷。此外,您可能希望将原始数组存储为副本,以便可以轻松“重置”这些数字。

#2


3  

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的原始方法没有太大的不同。该方法工作正常,因为它没有从数组中以偏置的方式进行采样。

#3


2  

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

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

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());    
}

#4


0  

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.

我相信有几种方法可以做到这一点,但是你可以把所有的数字放到一个堆栈中,把它们都堆起来,然后弹出来,得到随机的数字。或者,每次都随机地搜索它,然后从堆栈中删除它。

#5


0  

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

>生成一个随机数并将其添加到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 !

>生成一个新的随机数并遍历CHECK_ARRAY,如果找到26,然后忽略,否则如果找到duplicate,则重新生成一个随机数,继续第三步,直到找到一个唯一的随机数!

#6


0  

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.

在其他的解决方案中,我认为他们忘记了搜索索引。

#7


0  

<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>

#8


0  

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

假设您需要从范围1中选择一个随机数……5并排除2、4的值:

  • Pick a random number from the range 1...3
  • 从范围1…3中选择一个随机数
  • Sort excluded number list
  • 这种排除列表数量
  • For each excluded number less than the random number: add one to the random number
  • 对于每个被排除的数字小于随机数:在随机数中增加一个

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]);