JavaScript-如何在不替换的情况下随机采样项目?

JavaScript-如何在不替换的情况下随机采样项目?,javascript,random,probability,random-sample,Javascript,Random,Probability,Random Sample,JavaScript 我试过寻找这样的东西,但我找不到 这是一个简单的想法: a。取一个0到10之间的随机数 b。假设滚动的随机数是3 c。然后,保存号码(3) d。现在,再取一个介于0到10之间的随机数,但它不能是3,因为它已经出现了 Var rnd = getRnd(); While(rnd != lastRnd) rnd = getRnd(); 其中getRnd()是一个生成随机数的函数 实际上,您必须检查当前的随机数是否在数组中。。。如果您的可能随机数列表很小,请注意无限循环。一

JavaScript

我试过寻找这样的东西,但我找不到

这是一个简单的想法:

a。取一个0到10之间的随机数

b。假设滚动的随机数是3

c。然后,保存号码(3)

d。现在,再取一个介于0到10之间的随机数,但它不能是3,因为它已经出现了

Var rnd = getRnd();

While(rnd != lastRnd)
  rnd = getRnd();
其中
getRnd()
是一个生成随机数的函数


实际上,您必须检查当前的随机数是否在数组中。。。如果您的可能随机数列表很小,请注意无限循环。

一种解决方案是生成一个包含所有要拾取的值的数组(一个“bucket”),在这种情况下,所有值都是从0到10。然后从阵列中随机选取一个,并将其从桶中移除。请注意,下面的示例不检查bucket是否为空,因此如果调用下面的函数超过10次,则会出现错误

var bucket = [];

for (var i=0;i<=10;i++) {
    bucket.push(i);
}

function getRandomFromBucket() {
   var randomIndex = Math.floor(Math.random()*bucket.length);
   return bucket.splice(randomIndex, 1)[0];
}

// will pick a random number between 0 and 10, and can be called 10 times
console.log(getRandomFromBucket());
var bucket=[];

对于(var i=0;i,您可以使用如下内容:

/**
* range Get an array of numbers within a range
* @param min {number} Lowest number in array
* @param max {number} Highest number in array
* @param rand {bool} Shuffle array
* @return {array}
*/
range: function( min, max, rand ) {
  var arr = ( new Array( ++max - min ) )
    .join('.').split('.')
    .map(function( v,i ){ return min + i })
  return rand
    ? arr.map(function( v ) { return [ Math.random(), v ] })
       .sort().map(function( v ) { return v[ 1 ] })
    : arr
}
并像这样使用它:

var arr = range( 1, 10, true )
现在,您有了一个数组,其中10个数字按随机顺序排列,从1到10,并且从不重复。因此,接下来您可以执行以下操作:

arr.forEach(function( num, i ) { 
  // do something, it will loop 10 times 
  // and num will always be a different number
  // from 1 to 10
});

只是为了好玩:源自@answer a“bucket构造函数”

function RandomBucket(from,until){
  min = (Number(from) || 0);
  max = (Number(until) || 10)+1;
  this.bucket = String(Array(max-min)).split(',').map(function(i){
     return min++;
  });

  if (!RandomBucket.prototype.get){
   RandomBucket.prototype.get = function(){
      var randomValue = 
        this.bucket.length < 2
        ? this.bucket.shift()
        : this.bucket.splice(Math.floor(Math.random()*this.bucket.length),1);
       return randomValue || 'bucket empty';
      };
  }
}
函数随机桶(从,到){
最小值=(数字(从)| | 0);
最大值=(数字(直到)| | 10)+1;
this.bucket=String(数组(max-min)).split(',').map(函数(i){
返回min++;
});
if(!RandomBucket.prototype.get){
RandomBucket.prototype.get=函数(){
var随机值=
此.bucket.length<2
?此.bucket.shift()
:this.bucket.splice(Math.floor(Math.random()*this.bucket.length),1);
返回随机值| |‘bucket empty’;
};
}
}
有关用法示例,请参见使用:


大多数情况下,我会坚持其他答案所建议的方法——即创建一个可能性数组,创建一个混合版本,然后将前n个值作为示例(所有操作都简单、通用,并且可以不可变地实现)

然而,如果与您想要使用的内存量相比,或者与您想要绘制的随机值相比,可能性的范围很大(尽管@Strilles solution使用内存,但不会绘制很多随机值,因此即使对于我下面的用例,这也可能是最好的)

按照您的问题提出的解决方案可能如下所示:

/**
* range Get an array of numbers within a range
* @param min {number} Lowest number in array
* @param max {number} Highest number in array
* @param rand {bool} Shuffle array
* @return {array}
*/
range: function( min, max, rand ) {
  var arr = ( new Array( ++max - min ) )
    .join('.').split('.')
    .map(function( v,i ){ return min + i })
  return rand
    ? arr.map(function( v ) { return [ Math.random(), v ] })
       .sort().map(function( v ) { return v[ 1 ] })
    : arr
}
//从[from,to]范围中选择n个整数(包括两侧),
//对于n的大值,不要使用此方法
//根据需要从随机源获取随机值
无替换的函数RandomNumbers(n,from,to,randomSource=Math.random){
常量结果=[];
for(设i=0;i如果(结果[j],问题是什么?您是否尝试编写程序?如果是,您在哪里遇到了问题?因为程序的总体思路已经存在(您的子任务列表听起来不错),应该有效。你的问题没有明确定义。第一项和第二项被选择的概率必须相等,还是故意不同?是的,我当然试过了,互联网上有很多关于用JS生成随机数的代码。但我不知道如何使c)和d)相等理论上,如果你真的不走运,这可能会循环很长一段时间。最理想、最优雅的解决方案!@skovalyov可能是最优雅的,但不是最理想的-上次我测试时,
splice
的速度大约是手动用
for
循环洗牌元素速度的一半。如果你不需要将数组保持在ord中呃,那么最快的方法就是将最后一个元素移动到随机位置。@Neil的响应是最理想的。简单就是优雅master@ShawnCicoria-MSFT我并不是在抱怨它的优雅,但你可以使用分析来确定最佳的解决方案,而不是简单性。