数组乱序---洗牌算法

180 阅读2分钟

场景
在我的一个项目中,需要用到随机播放这个功能,就研究了一下,记录如下

洗牌算法

原理
1.倒序循环这个数组
2.取范围从 0 到 i 的随机索引 j
3. i 与 j 位置交换
4.直到循环至数组的首个元素

function shuffle(arr) {
    let i = arr.length;
    for(let i = arr.length-1; i > 0;i--) {
        let j = Math.floor(Math.random() * i);
        var t = arr[i]
        arr[i] = arr[j]
        arr[j] = t
    }
    return arr;
}
var arr = [1,2,3,4,5,6,7,8,9];
console.log(shuffle(arr)); //  [6, 3, 9, 1, 8,7, 2, 4, 5]

看一下变换过程 随机数向下取整

[1,2,3,4,5,6,7,8,9] 

// 第一次 0 ~ 8  随机数 和 最后一个交换 
// 5 和 9 交换
[1, 2, 3, 4, 9,6, 7, 8, 5]

// 第二次 0 ~ 7 随机数 和 最后倒数第二个交换
// 4 和 8 交换
[1, 2, 3, 8, 9,6, 7, 4, 5]

// 第三次 0 ~ 6 随机数 和 最后倒数第三个交换
// 2 和 7 交换
[1, 7, 3, 8, 9,6, 2, 4, 5]

// 第四次 0 ~ 5 随机数 和 最后倒数第四个交换
// 7 和 6 交换
[1, 6, 3, 8, 9,7, 2, 4, 5]

// 第五次 0 ~ 4 随机数 和 最后倒数第五个交换
// 8 和 9 交换
[1, 6, 3, 9, 8,7, 2, 4, 5]

// 第六次 0 ~ 3 随机数 和 最后倒数第六个交换
// 1 和 9 交换
[9, 6, 3, 1, 8,7, 2, 4, 5]

// 第七次 0 ~ 2 随机数 和 最后倒数第七个交换
// 9 和 3交换
[3, 6, 9, 1, 8,7, 2, 4, 5]

// 第八次 0 ~ 1 随机数 和 最后倒数第八个交换
// 3 和 6 交换
[6, 3, 9, 1, 8,7, 2, 4, 5]

可以看出 总共循环了八次,深度打乱了原位置数据

下面来看看es6进阶

function shuffle(arr) {
    let i = arr.length;
    while (i) {
        let j = Math.floor(Math.random() * i--);
        [arr[j], arr[i]] = [arr[i], arr[j]];
    }
    return arr;
}

sort

简易打乱 sort 有的时候大部分位置还是在原地

function shuffle(arr) {
    arr.sort((a,b) => {
        return Math.random() - 0.5
    }) 
    return arr
}