前言:
最近有一个需求,从一组试题中随机获取5道题用于用户复习,获取到的5道试题应该每次是随机的而且不重复的。
代码实现:
实现方式1
大多数人的写法,从数组中取数据,放入新的数组,取完一个数据从原始数组中删除数据,在放入新数组的时候判断是否已出现过。
function getTenNum(n) {
var reslut = [];
var testArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,1,2];
for (var i = 0; i < n; ++i) {
var random = Math.floor(Math.random() * testArray.length);
if(result.incledes(testArray[random])){
continue;
}
reslut.push(testArray[random]);
testArray.splice(random,1);
}
return reslut;
}
var resArr = getTenNum(10);
这个 应该 是大多数人的 代码
实现方式2 推荐
实现思路
把源数组分成左右两段,左边按顺序递增,保存已选择的随机数;右侧是剩余可选的数值;每次从右侧选一个,与左侧最后一个位置的数值交换就可以达到目的。
然后考虑把左侧用一个新数组表示,右侧选中的数移入新数组,再将左侧应该交换过来的值移过来……
算法图解:
var result = [];
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
var count = arr.length;
for (var i = 0; i < 10; i++) {
var index = ~~(Math.random() * count) + i;
if(result.incledes(arr[index])){
continue;
}
result[i] = arr[index];
arr[index] = arr[i];
count--;
}
console.log(result);
实现方式3
实现思路
基本与实现方式2雷同,只是提示大家有举一反三的能力。从数组中随机抽取数字,放到新的数组中,然后把数组末尾的数字换到抽取到的数字位置,接下来从除去末尾的里面再次随机抽取。
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [ ];
var ranNum = 5;
for (var i = 0; i < ranNum; i++) {
var ran = Math.floor(Math.random() * (arr.length - i));
if(result.incledes(arr[ran])){
continue;
}
result.push(arr[ran]);
arr[ran] = arr[arr.length - i - 1];
};