数组乱序
顾名思义,数组乱序就是把数组存储的值的顺序都打乱。
Fisher–Yates shuffle
著名的洗牌算法,原理就是遍历数组元素,将当前元素与随机抽取的一个剩余元素进行交换。
下列表格遍历元素是从后往前:
发表于: 2019-10-26 21:24:37
0 973
顾名思义,数组乱序就是把数组存储的值的顺序都打乱。
著名的洗牌算法,原理就是遍历数组元素,将当前元素与随机抽取的一个剩余元素进行交换。
下列表格遍历元素是从后往前:
function shuffle(arr) { for (let i=arr.length-1; i>=0; i--) { let rIndex = Math.floor(Math.random()*(i+1)); // 打印交换值
// console.log(i, rIndex);
let temp = arr[rIndex];
arr[rIndex] = arr[i];
arr[i] = temp;
} return arr;
}
shuffle([1,2,3,4,5,6]); // [1, 5, 3, 6, 4, 2]
现在测试一下是否真的实现了乱序:
// 使用 res 存储结果let res = {};let times = 100000;for (let i=0; i<times; i++) { // 使用 [1, 2, 3] 进行简单测试
let key = JSON.stringify(shuffle([1, 2, 3]));
res[key] ? res[key]++ : res[key] = 1;
}for (let key in res) {
res[key] = Number.parseFloat(res[key]/times *100 ).toFixed(3) + '%';
}// 从结果可以看出是实现了真正的乱序的res;
/*
[1,2,3]: "16.514%"
[1,3,2]: "16.764%"
[2,1,3]: "16.606%"
[2,3,1]: "16.587%"
[3,1,2]: "16.712%"
[3,2,1]: "16.817%"
*/
在乱序的同时,固定一个下标的值,使其位置不变,方法有很多,这里只给出一种:
function shuffle(arr, index) { let res = []; // 取出固定值
let fix = arr.splice(index, 1)[0]; for (let i=arr.length-1; i>=0; i--) { let rIndex = Math.floor(Math.random()*(i+1));
res.push(arr[rIndex]);
arr.splice(rIndex, 1);
} // 将固定值放入指定位置
res.splice(index, 0, fix); return res;
}// 多次运行,可以看出数组下标为 1 的值始终是固定的shuffle([1,2,3,4,5,6], 1);// [5, 2, 6, 3, 1, 4]// [5, 2, 6, 3, 4, 1]// [3, 2, 4, 6, 1, 5]
这里同样测试一下是否实现了真正的乱序:
let res = {};let times = 100000;for (let i=0; i<times; i++) { // 使用 [1, 2, 3] 进行简单测试,固定数组下标 1 的值
let key = JSON.stringify(shuffle([1, 2, 3], 1));
res[key] ? res[key]++ : res[key] = 1;
}for (let key in res) {
res[key] = Number.parseFloat(res[key]/times *100 ).toFixed(3) + '%';
}// 固定的同时,依然是乱序的res;/*
[1,2,3]: "49.976%"
[3,2,1]: "50.024%"
*/
评论