• JS 数组中 reduce 方法详解


    一、reduce 方法

    reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
    也就是说,这个累加器会从第一个累加值开始,不断对累加值和数组中的后续元素调用该累加器,直到数组中的最后一个元素,最后返回得到的累加值。

    1、语法

    array.reduce(callback, initialValue)
    

    2、参数说明

    reduce 参数 reduce 参数说明
    callback(total, currentValue, index, arr) 必需。用于执行每个数组元素的累加器函数。
    函数参数:
    累加器参数 累加器参数说明
    total 必需。初始值, 或者计算结束后的返回值。
    currentValue 必需。当前元素
    currentIndex 可选。当前元素的索引
    arr 可选。当前元素所属的数组对象。
    initialValue 可选。传递给函数的初始值

    3、应用

    ① 简单示例

    var items = [10, 100, 1000];
    
    // 累加器函数
    var reducer = function add(sumSoFar, item) { return sumSoFar + item; };
    
    var total = items.reduce(reducer, 1);
    
    console.log(total); // 1111
    

    可以看出,reduce 函数根据初始值 1,不断的进行叠加,完成最简单的总和的实现

    ② 返回对象

    reduce 函数的返回结果类型和传入的初始值相同,上个实例中初始值为 number 类型,同理,初始值也可为 object 类型

    var items = [10, 100, 1000];
    
    // 累加器函数
    var reducer = function add(sumSoFar, item) {
      sumSoFar.sum = sumSoFar.sum + item;
      return sumSoFar;
    };
    
    var total = items.reduce(reducer, { sum: 1 });
    
    console.log(total); // {sum: 1111}
    

    ③ 多维度的数据叠加

    使用 reduce 方法可以完成多维度的数据叠加
    如上例中的初始值 {sum: 0},这仅仅是一个维度的操作,如果涉及到了多个属性的叠加,如 {sum: 0,totalInEuros: 0,totalInYen: 0},则需要相应的逻辑进行处理

    在下面的方法中,采用分而治之的方法,即将 reduce 函数第一个参数 callback 封装为一个数组,由数组中的每一个函数单独进行叠加并完成 reduce 操作。所有的一切通过一个 manager 函数来管理流程和传递初始参数。

    var manageReducers = function (reducers) {
      return function (state, item) {
        return Object.keys(reducers).reduce(
          function (nextState, key) {
            reducers[key](state, item);
            return state;
          },
          {}
        );
      }
    };
    

    上面就是 manager 函数的实现,它需要 reducers 对象作为参数,并返回一个 callback 类型的函数,作为 reduce 的第一个参数。在该函数内部,则执行多维的叠加工作(Object.keys())

    通过这种分治的思想,可以完成目标对象多个属性的同时叠加,完整代码如下:

    var reducers = {
      totalInEuros: function (state, item) {
        return state.x += item.num * 1;
      },
      totalInYen: function (state, item) {
        return state.y += item.num * 2;
      }
    };
    
    var manageReducers = function (reducers) {
      return function (state, item) {
        return Object.keys(reducers).reduce(
          function (nextState, key) {
            reducers[key](state, item);
            return state;
          },
          {}
        );
      }
    };
    
    var bigTotalPriceReducer = manageReducers(reducers);
    var initialState = {
      x: 1,
      y: 1
    };
    var items = [
      {
        num: 10
      },
      {
        num: 100
      },
      {
        num: 1000
      }
    ];
    var totals = items.reduce(bigTotalPriceReducer, initialState);
    
    console.log(totals);  // {x: 1111, y: 2221}
    

    ③ 场景应用

    某同学的期末成绩如下表示

    var result = [
      {
        subject: 'chinese',
        score: 85
      },
      {
        subject: 'math',
        score: 95
      },
      {
        subject: 'english',
        score: 90
      }
    ];
    

    如何求该同学的总成绩?

    var sum = result.reduce(function (prev, cur) {
      return cur.score + prev;
    }, 0);
    

    假设该同学因为违纪被处罚在总成绩总扣 10 分,只需要将初始值设置为 -10 即可:

    var sum = result.reduce(function (prev, cur) {
      return cur.score + prev;
    }, -10);
    

    我们来给这个例子增加一点难度
    假如该同学的总成绩中,各科所占的比重不同,分别为 50%,30%,20%,我们应该如何求出最终的权重结果呢?

    解决方案如下:

    var dis = {
      math: 0.5,
      chinese: 0.3,
      english: 0.2
    }
    
    var sum = result.reduce(function (prev, cur) {
      return cur.score + prev;
    }, -10);
    
    var qsum = result.reduce(function (prev, cur) {
      return cur.score * dis[cur.subject] + pre;
    }, 0)
    
    console.log(sum, qsum);
    
  • 相关阅读:
    解决eclipse中egit中的cannot open git-upload-pack问题
    局部更新listview的问题(只更新某个item)
    漂亮的自制java验证码
    Myeclipse:No projects are available for deployment to this server!
    Java获取时间与系统时间相差8小时终极解决方案
    [转]SpringMVC日期类型转换问题三大处理方法归纳
    utf8乱码解决方案[适合tomcat部署的jsp应用]
    我的AndroidStudio设置
    清空session的方法
    JavaScript和JQuery获取DIV的值
  • 原文地址:https://www.cnblogs.com/Leophen/p/14833003.html
Copyright © 2020-2023  润新知