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);
posted @ 2021-03-01 21:01  Leophen  阅读(646)  评论(0编辑  收藏  举报