洗牌算法
今天在做一个随机数,感觉js里面的random函数不够随机,于是想着写一个更加松散的洗牌算法,可以用于随机播放列表随机排序列表等场景。
逻辑
- 拿到原始数据
- 使用for循环来处理这个数据
- 根据for循环中的i值随机生成一个0-max的整数
- 拿到随机生成的坐标后,当前坐标和随机生成的坐标做交换
- 待for循环处理完成后,返回新的数据,完成洗牌
这样处理的目的就是把数组打的更乱,相当于洗牌更松散,也就达成了比random更加随机的效果。
开工
我使用的是Vue,所以还是在脚手架项目里进行操作。
新建一个公共js文件utils.js来存放封装的函数,以便于其它地方使用的时候直接调用。
- 首先使用slice函数初始化一个数据,source为传入的源数据。
const arr = source.slice()
- 构造一个生成0-max下标的函数。这个函数为生成的随机数下标做服务。
function getRandomInt (max) {
return Math.floor(Math.random() * (max + 1))
}
这里这里的返回值为0-max的随机整数,使用floor来处理。
方法参数解读:
Math.floor()
:返回小于或等于一个给定数字的最大整数,通俗易懂的说就是向下取整;
Math.random()
:返回一个浮点数,范围从0到1,包括0不包括1,数学理解为[0,1);
- 定义一个交换函数,也就是众所周知的交换排序,感觉这段代码能刻在DNA里面了。
function swap (arr, i, j) {
const t = arr[i]
arr[i] = arr[j]
arr[j] = t
}
- 最后利用for循环来进行处理并返回新数组
for (let i = 0; i < arr.length; i++) {
const j = getRandomInt(i)
swap(arr, i, j)
}
return arr
全部代码
// 洗牌算法
export function shuffle(source) {
const arr = source.slice()
for (let i = 0; i < arr.length; i++) {
const j = getRandomInt(i)
swap(arr, i, j)
}
return arr
}
// 获取0-max之间的函数
function getRandomInt (max) {
return Math.floor(Math.random() * (max + 1))
}
// 交换坐标
function swap (arr, i, j) {
const t = arr[i]
arr[i] = arr[j]
arr[j] = t
}