zoukankan      html  css  js  c++  java
  • JS: 数组乱序

    数组乱序


    顾名思义,数组乱序就是把数组存储的值的顺序都打乱。

    Fisher–Yates shuffle


    著名的洗牌算法,原理就是遍历数组元素,将当前元素与随机抽取的一个剩余元素进行交换。

    下列表格遍历元素是从后往前:

    随机数范围 随机数 原始数据 结果
    1 2 3 4 5 6
    [ 0 , 5 ] 1 1 6 3 4 5 2
    [ 0 , 4 ] 3 1 6 3 5 4 2
    [ 0 , 3 ] 1 1 5 3 6 4 2
    [ 0 , 2 ] 2 1 5 3 6 4 2
    [ 0 , 1 ] 1 1 5 3 6 4 2
    [ 0 , 0 ] 0 1 5 3 6 4 2

    代码如下:

    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%"
    */
    

    注意


    需要注意的是,因为数组是引用类型,所以上面的方法都会改变原数组,要想不改变原数组只需稍稍改动一下代码即可,这个很简单,就不写了。

  • 相关阅读:
    ajax提交 返回中文乱码问题
    JAVA spring配置文件总结
    缓存线程池的作用
    myclipse里有感叹号的问题,希望可以帮到各位
    html 鼠标样式 鼠标悬停 小手样式
    在div中注入html代码
    发送邮件的几种方法(C#发邮件 和 js前台实现都有)C#后台自动发邮件 js发邮件
    Angular js 复制粘贴
    C# ASP 面试题 2017
    cocos-lua3.17 cocos studio lua动画使用
  • 原文地址:https://www.cnblogs.com/guolao/p/10173537.html
Copyright © 2011-2022 走看看