JavaScript-如何在不替换的情况下随机采样项目?
JavaScript 我试过寻找这样的东西,但我找不到 这是一个简单的想法: a。取一个0到10之间的随机数 b。假设滚动的随机数是3 c。然后,保存号码(3) d。现在,再取一个介于0到10之间的随机数,但它不能是3,因为它已经出现了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()是一个生成随机数的函数 实际上,您必须检查当前的随机数是否在数组中。。。如果您的可能随机数列表很小,请注意无限循环。一
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我并不是在抱怨它的优雅,但你可以使用分析来确定最佳的解决方案,而不是简单性。