【发布时间】:2013-05-24 05:37:49
【问题描述】:
除了数组拼接之外,还有什么方法可以用来在两个数字之间生成一个随机数而不重复,直到生成这两个数字之间的所有数字?除了拼接之外,改组技术或任何其他数组方法都非常有用。
【问题讨论】:
-
Fisher-Yates 洗牌:stackoverflow.com/questions/2450954/…
标签: javascript
除了数组拼接之外,还有什么方法可以用来在两个数字之间生成一个随机数而不重复,直到生成这两个数字之间的所有数字?除了拼接之外,改组技术或任何其他数组方法都非常有用。
【问题讨论】:
标签: javascript
首先我们使用 FisherYates 实现 (credit goes to @ChristopheD) 并扩展数组原型以提供 shuffle 函数
function arrayShuffle () {
var i = this.length, j, temp;
if ( i === 0 ) return false;
while ( --i ) {
j = Math.floor( Math.random() * ( i + 1 ) );
temp = this[i];
this[i] = this[j];
this[j] = temp;
}
}
Array.prototype.shuffle =arrayShuffle;
var numbers = new Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.shuffle();
现在使用pop 方法,我们从种子中获取一个数字,直到它为空
numbers.pop(); //returns a number
为了确保我们有一个填充了start 和end 范围内数字的数组,我们使用一个简单的循环来创建我们的种子。
var start = 1;
var end = 5;
var numbers = new Array();
for (var i = start; i <= end; i++) {
numbers.push(i);
}
这是jsfiddle上的示例
更新:让 fisherYates 算法更高效地洗牌
【讨论】:
N**N同样可能的改组,而N元素的排列数量是N!,并且通常N**N不是N!的精确倍数.
is an algorithm for generating a random permutation of a finite set—in plain terms, for randomly shuffling the set 但可能会发生,在所有排列出现之前,您再次获得相同的排列。如果要避免这种情况,则需要向 shuffle 方法提供一个数组数组,以检查新的 shuffle 数组是否尚未使用
在处理较小的数组时,我通常做的是随机排序数组:
yourArray.sort(function() { return 0.5 - Math.random() });
【讨论】:
试试这个http://jsbin.com/imukuh/1/edit:
function randRange(min, max) {
var result = [];
for (var i=min; i<=max; i++) result.push(i);
return result.map(function(v){ return [Math.random(), v] })
.sort().map(function(v){ return v[1] });
}
console.log(randRange(1,5));
// [4, 3, 1, 5, 2]
// [3, 5, 2, 4, 1]
// [1, 5, 2, 3, 4]
// [3, 2, 5, 1, 4]
// ...
【讨论】: