如果我理解正确,那么您只是在寻找数字 1-10 的排列(即随机化且不重复的数字)?也许尝试在开始时生成这些数字的随机列表一次,然后按照自己的方式处理这些数字?
这将计算 中数字的随机排列nums
:
var nums = [1,2,3,4,5,6,7,8,9,10],
ranNums = [],
i = nums.length,
j = 0;
while (i--) {
j = Math.floor(Math.random() * (i+1));
ranNums.push(nums[j]);
nums.splice(j,1);
}
因此,例如,如果您正在寻找 1 到 20 之间的随机数也是偶数,那么您可以使用:
nums = [2,4,6,8,10,12,14,16,18,20];
然后通读ranNums
以回忆随机数。
正如您在您的方法中发现的那样,这不会冒越来越多的时间来查找未使用的数字的风险。
编辑:阅读本文并在jsperf上运行测试后,Fisher-Yates Shuffle 似乎是一种更好的方法:
function shuffle(array) {
var i = array.length,
j = 0,
temp;
while (i--) {
j = Math.floor(Math.random() * (i+1));
// swap randomly chosen element with current element
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
基本上,通过避免使用“昂贵”的数组操作会更有效。
奖金编辑:另一种可能性是使用生成器(假设您有支持):
function* shuffle(array) {
var i = array.length;
while (i--) {
yield array.splice(Math.floor(Math.random() * (i+1)), 1)[0];
}
}
然后使用:
var ranNums = shuffle([1,2,3,4,5,6,7,8,9,10]);
ranNums.next().value; // first random number from array
ranNums.next().value; // second random number from array
ranNums.next().value; // etc.
一旦你遍历了洗牌数组中的所有元素,ranNums.next().value
最终将评估为where 。undefined
总体而言,这不会像 Fisher-Yates Shuffle 那样有效,因为您仍在splice
处理数组。但不同之处在于,您现在仅在需要时才进行这项工作,而不是预先完成所有工作,因此根据您的用例,这可能会更好。