• javascript:Array.prototype.reduce()的使用场景


    reduce()方法的使用场景

    1、语法

    array.reduce((previousValue,currentValue,currentIndex,array)=>{},initialValue)
    对数组累计执行回调函数并返回最终结果
    在这里插入图片描述
    在这里插入图片描述

    2、使用场景

    2.1 数组元素累计求和

    // 不设置初始值initialValue时
    let result1 = arr.reduce((previousValue,currentValue,arr) => {
        console.log(previousValue,"previousValue ============");
        console.log(currentValue,"currentValue ============");
        return previousValue + currentValue
    })
    
    console.log(result1); // 15
    
    // 设置初始值initialValue时
    let initialValue = 0
    let result2 = arr.reduce((previousValue,currentValue,arr) => {
        console.log(previousValue,"previousValue ============");
        console.log(currentValue,"currentValue ============");
        return previousValue + currentValue
    },initialValue)
    console.log(result2); // 15
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.2 二维数组扁平化

    let arr = [
        [20,30,20,10,32],
        [21,20,24,19,92],
        [20,43,20,20,32],
        [70,30,29,10,12],
    ]
    
    let result = arr.reduce((previousValue,currentValue) => {
        return previousValue.concat(currentValue)
    },[])
    
    console.log(result);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.3 统计数组中元素出现的频数

    const arr = [
        "a", "b", "a",, "a", "b", "a", "b", "a", "a", "a", "a", "a", "a", "b", "b", "b",
        "c", "c", "c", "c", "a", "b", "a", "b", "a"
    ]
    
    const result = arr.reduce(
        (previousValue, currentValue) => {
            if(currentValue in previousValue){
                previousValue[currentValue] ++;
            }else{
                previousValue[currentValue] = 1;
            }
            return previousValue;
        }, 
        {}
    )
    
    console.log(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.3 对数组中的对象元素分组分类

    const arr = [
        { 年级: "2017级", 学院: "计算机学院", 专业: "物联网" },
        { 年级: "2017级", 学院: "计算机学院", 专业: "计算机科学" },
        { 年级: "2018级", 学院: "计算机学院", 专业: "软件工程" },
        { 年级: "2019级", 学院: "计算机学院", 专业: "软件工程" },
        { 年级: "2019级", 学院: "计算机学院", 专业: "物联网" },
        { 年级: "2020级", 学院: "计算机学院", 专业: "物联网" },
        { 年级: "2020级", 学院: "计算机学院", 专业: "计算机科学" },
        { 年级: "2020级", 学院: "计算机学院", 专业: "软件工程" },
        { 年级: "2017级", 学院: "电气学院", 专业: "自动化" },
        { 年级: "2018级", 学院: "电气学院", 专业: "自动化" },
        { 年级: "2019级", 学院: "电气学院", 专业: "自动化" },
        { 年级: "2020级", 学院: "电气学院", 专业: "自动化" },
    ]
    
    
    // 根据指定字段的指定值获取分组  
    function getByTarget(arr, target, targetValue) {
        // 如果没有指定具体年级,例如: 按照年级分组 
        if (!targetValue) {
            const result = arr.reduce(
                (previousValue, currentValue) => {
                    // 拿到当前要分组的条件
                    // 例如,currentValue是{ 年级: "2017级", 学院: "计算机学院", 专业: "物联网" }这样一个对象
                    // 那么,currentValue[target] 就是年级或者学院或者专业
                    let currentTargetValue = currentValue[target]
    
                    // 如果previousValue对象中没有值,则创建一个新数组
                    if (!previousValue[currentTargetValue]) {
                        previousValue[currentTargetValue] = []
                    }
    
                    // 将符合条件的添加到previousValue[currentTargetValue]数组中
                    previousValue[currentTargetValue].push(currentValue)
                    return previousValue;
                },
                {}
            )
            return result;
        }
    
        // 如果还指定了具体年级
        let initObj = {}
        initObj[targetValue] = [];
        const result = arr.reduce(
            (previousValue, currentValue) => {
    
                // 不是目标值直接跳过
                if (currentValue[target] !== targetValue) {
                    return previousValue;
                }
    
                // 符合要求则加入
                previousValue[targetValue].push(currentValue);
    
                return previousValue;
            },
            initObj
        )
        return result;
    }
    
    
    result05_01 = getByTarget(arr, "专业")
    result05_02 = getByTarget(arr, "学院")
    result05_03 = getByTarget(arr, "年级")
    
    // 这里是为了确保函数返回值是一个map而不是数组(统一返回格式) 重在思路
    result05_04 = getByTarget(arr, "年级", "2017级")["2017级"]
    result05_05 = getByTarget(arr, "学院", "计算机学院")["计算机学院"]
    result05_06 = getByTarget(arr, "专业", "自动化")["自动化"]
    
    console.log("按专业分类");
    console.log(result05_01)
    console.log("按学院分类");
    console.log(result05_02)
    console.log("按年级分类");
    console.log(result05_03)
    console.log("取2017级");
    console.log(result05_04)
    console.log("取计算机学院");
    console.log(result05_05)
    console.log("取自动化专业");
    console.log(result05_06)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    结果:

    按专业分类
    {
    ‘物联网’: [
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ }
    ],
    ‘计算机科学’: [
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ }
    ],
    ‘软件工程’: [
    { ‘年级’: ‘2018级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ }
    ],
    ‘自动化’: [
    { ‘年级’: ‘2017级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2018级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ]
    }
    按学院分类
    {
    ‘计算机学院’: [
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2018级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ }
    ],
    ‘电气学院’: [
    { ‘年级’: ‘2017级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2018级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ]
    }
    按年级分类
    {
    ‘2017级’: [
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2017级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ],
    ‘2018级’: [
    { ‘年级’: ‘2018级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2018级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ],
    ‘2019级’: [
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ],
    ‘2020级’: [
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ]
    }
    取2017级
    [
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2017级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ]
    取计算机学院
    [
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2017级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2018级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘物联网’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘计算机科学’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘计算机学院’, ‘专业’: ‘软件工程’ }
    ]
    取自动化专业
    [
    { ‘年级’: ‘2017级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2018级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2019级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ },
    { ‘年级’: ‘2020级’, ‘学院’: ‘电气学院’, ‘专业’: ‘自动化’ }
    ]


    或者更简单点如下:

    const arr = [
        { 年级: "2017级", 学院: "计算机学院", 专业: "物联网" },
        { 年级: "2017级", 学院: "计算机学院", 专业: "计算机科学" },
        { 年级: "2018级", 学院: "计算机学院", 专业: "软件工程" },
        { 年级: "2019级", 学院: "计算机学院", 专业: "软件工程" },
        { 年级: "2019级", 学院: "计算机学院", 专业: "物联网" },
        { 年级: "2020级", 学院: "计算机学院", 专业: "物联网" },
        { 年级: "2020级", 学院: "计算机学院", 专业: "计算机科学" },
        { 年级: "2020级", 学院: "计算机学院", 专业: "软件工程" },
        { 年级: "2017级", 学院: "电气学院", 专业: "自动化" },
        { 年级: "2018级", 学院: "电气学院", 专业: "自动化" },
        { 年级: "2019级", 学院: "电气学院", 专业: "自动化" },
        { 年级: "2020级", 学院: "电气学院", 专业: "自动化" },
    ]
    
    
    // 根据指定字段的指定值获取分组  
    function getByTarget(arr, target) {
        // 如果没有指定具体年级,例如: 按照年级分组 
            const result = arr.reduce(
                (previousValue, currentValue) => {
                    // 拿到当前要分组的条件
                    // 例如,currentValue是{ 年级: "2017级", 学院: "计算机学院", 专业: "物联网" }这样一个对象
                    // 那么,currentValue[target] 就是年级或者学院或者专业
                    let currentTargetValue = currentValue[target]
    
                    // 如果previousValue对象中没有值,则创建一个新数组
                    if (!previousValue[currentTargetValue]) {
                        previousValue[currentTargetValue] = []
                    }
    
                    // 将符合条件的添加到previousValue[currentTargetValue]数组中
                    previousValue[currentTargetValue].push(currentValue)
                    return previousValue;
                },
                {}
            )
            return result;
    }
    
    // 先进行总体分组
    result05_01 = getByTarget(arr, "专业")
    result05_02 = getByTarget(arr, "学院")
    result05_03 = getByTarget(arr, "年级")
    
    // 再进行具体分组,例如取出物联网专业
    console.log(result05_01["物联网"]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    2.4 数组元素去重

    let arr = ["a","b","c","d","a","b","e","c","d"]
    let result = arr.reduce((previousValue,currentValue) => {
        if(previousValue.indexOf(currentValue) === -1){
            previousValue.push(currentValue)
        }
        return previousValue
    },[])
    
    console.log(result);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.5 模拟实现map函数

    Array.prototype.myMap = function(func, callbackThis){
        // 最终返回新的数组
        let res = [];
    
        // 定义回调函数的执行环境
        // call 第2个参数传入null 则this指向全部对象
        let cbThis = callbackThis || null;
    
        this.reduce(
            (prev, next, index, arr)=>{
                // 传入map回调函数拥有的参数
                // 把每一项的执行结果push进入res
                res.push(func.call(cbThis, next, index, arr));
                
            }, 
            null);
        
            return res;
    }
    let arr = [1,2,3,4,5,6,7,8]
    let result = arr11.myMap(Math.sqrt)
    
    console.log(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3、自定义实现reduce函数

    /**
     * @description: 自定义数组的reduce方法
     * @params callback 回调函数
     * @params initialValue 初始值
     * @return 返回处理结果
     */
    Array.prototype.myReduce = function (callback, initialValue) {
        if (this == null) {
            throw new TypeError('this is null or undefined');
        }
    
        if (typeof callback !== 'function') {
            throw new TypeError(`${callback} is not a function`);
        }
    
        console.log(this); // 传进来的数组对象
        const array = Object(this);
        const len = array.length >>> 0;
        let accumulator = initialValue;
    
        for (let i = 0; i < len; i++) {
            if (i in array) {
                accumulator = callback.call(undefined, accumulator, array[i], i, array);
            }
        }
    
        return accumulator;
    };
    
    // 使用
    let array = [1,2,3,4]
    
    let result = array.myReduce((pre,cur) => {
        pre.push(cur+1)
        return pre
    },[])
    
    console.log(result); // [2,3,4,5]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    或者循环实现

    var reduce = function (nums, fn, init) {
        if (nums.length === 0)
            return init
    
        nums.forEach((item, index) => {
            init = fn(init, item)
        })
    
        return init
    };
    
    // 被处理的数组
    let nums = [1, 2, 3, 4]
    // 初始值
    let init = 100
    // 回调函数
    function sum(accum, curr) { return accum + curr * curr; }
    
    console.log(reduce(nums, sum, init));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    设计模式学习(二十一):命令模式
    ceph操作
    x86 CPU架构
    DL在材料化学中(基于图像模型)的应用
    全球知名Web排名网站Alexe.com将关闭
    ROS-TCP-Connector and ROS-TCP-Endpoint
    SDUT—Python程序设计实验10&11(面向对象)
    Maven知识点总结
    动作捕捉助力无源上肢外骨骼的基础协调性评估
    blender基本操作
  • 原文地址:https://blog.csdn.net/lalala_dxf/article/details/127668917