详解JS数组Reduce()方法详解及高级技巧


Posted in Javascript onAugust 18, 2017

基本概念

reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。

语法:

arr.reduce(callback,[initialValue])
  • callback (执行数组中每个值的函数,包含四个参数)
  • previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
  • currentValue (数组中当前被处理的元素)
  • index (当前元素在数组中的索引)
  • array (调用 reduce 的数组)
  • initialValue (作为第一次调用 callback 的第一个参数。)

简单应用

例1:

var items = [10, 120, 1000];
// our reducer function
var reducer = function add(sumSoFar, item) { return sumSoFar + item; };
// do the job
var total = items.reduce(reducer, 0);
console.log(total); // 1130

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

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

例2:

var items = [10, 120, 1000];
// our reducer function
var reducer = function add(sumSoFar, item) {
 sumSoFar.sum = sumSoFar.sum + item;
 return sumSoFar;
};
// do the job
var total = items.reduce(reducer, {sum: 0});
console.log(total); // {sum:1130}

进阶应用

使用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.euros += item.price * 0.897424392;
 },
 totalInYen : function(state, item) {
  return state.yens += item.price * 113.852;
 }
};
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 = {euros:0, yens: 0};
var items = [{price: 10}, {price: 120}, {price: 1000}];
var totals = items.reduce(bigTotalPriceReducer, initialState);
console.log(totals);

在来一个例子:

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

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

如何求该同学的总成绩?

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);

再看一个例子,如何知道一串字符串中每个字母出现的次数?

var arrString = 'abcdaabc';
arrString.split('').reduce(function(res, cur) {
  res[cur] ? res[cur] ++ : res[cur] = 1
  return res;
}, {})

由于可以通过第二参数设置叠加结果的类型初始值,因此这个时候reduce就不再仅仅只是做一个加法了,我们可以灵活的运用它来进行各种各样的类型转换,比如将数组按照一定规则转换为对象,也可以将一种形式的数组转换为另一种形式的数组,大家可以动手去尝试一样。

[1, 2].reduce(function(res, cur) { 
  res.push(cur + 1); 
  return res; 
}, [])

koa的源码中,有一个only模块,整个模块就一个简单的返回reduce方法操作的对象:

var only = function(obj, keys){
 obj = obj || {};
 if ('string' == typeof keys) keys = keys.split(/ +/);
 return keys.reduce(function(ret, key){
  if (null == obj[key]) return ret;
  ret[key] = obj[key];
  return ret;
 }, {});
};

通过对reduce概念的理解,这个模块主要是想新建并返回一个obj对象中存在的keys的object对象。

var a = {
  env : 'development',
  proxy : false,
  subdomainOffset : 2
}
only(a,['env','proxy'])  // {env:'development',proxy : false}

总结

以上所述是小编给大家介绍的详解JS数组Reduce()方法详解及高级技巧,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
基于jquery的button默认enter事件(回车事件)。
May 18 Javascript
JavaScript 判断用户输入的邮箱及手机格式是否正确
Dec 08 Javascript
javascript实现模拟时钟的方法
May 13 Javascript
JSON相关知识汇总
Jul 03 Javascript
微信小程序 WebSocket详解及应用
Jan 21 Javascript
利用vue.js插入dom节点的方法
Mar 15 Javascript
JavaScript在控件上添加倒计时功能的实现代码
Jul 04 Javascript
原生js检测页面加载完毕的实例
Sep 11 Javascript
JS事件绑定的常用方式实例总结
Mar 02 Javascript
javascript实现函数柯里化与反柯里化过程解析
Oct 08 Javascript
Vue组件基础用法详解
Feb 05 Javascript
eslint+prettier统一代码风格的实现方法
Jul 22 Javascript
javascript将url解析为json格式的两种方法
Aug 18 #Javascript
Vue组件选项props实例详解
Aug 18 #Javascript
浅谈angular4 ng-content 中隐藏的内容
Aug 18 #Javascript
Node.JS更改Windows注册表Regedit的方法小结
Aug 18 #Javascript
浅谈Angular2 ng-content 指令在组件中嵌入内容
Aug 18 #Javascript
Vue中引入样式文件的方法
Aug 18 #Javascript
jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】
Aug 18 #jQuery
You might like
用PHP生成自己的LOG文件
2006/10/09 PHP
基于Discuz security.inc.php代码的深入分析
2013/06/03 PHP
PHP大小写问题:函数名和类名不区分,变量名区分
2013/06/17 PHP
php 根据url自动生成缩略图并处理高并发问题
2014/01/23 PHP
js 有框架页面跳转(target)三种情况下的应用
2013/04/09 Javascript
jQuery实现渐变弹出层和弹出菜单的方法
2015/02/20 Javascript
jQuery判断元素上是否绑定了指定事件的方法
2015/03/17 Javascript
使用jQuery的easydrag插件实现可拖动的DIV弹出框
2016/02/19 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
jQuery实用密码强度检测
2017/03/02 Javascript
jquery实现tab键进行选择后enter键触发click行为
2017/03/29 jQuery
ionic中的$ionicPlatform.ready事件中的通用设置
2017/06/11 Javascript
JavaScript定义函数_动力节点Java学院整理
2017/06/27 Javascript
vue拦截器实现统一token,并兼容IE9验证功能
2018/04/26 Javascript
qrcode生成二维码微信长按无法识别问题的解决
2019/04/04 Javascript
vue动态禁用控件绑定disable的例子
2019/10/28 Javascript
微信小程序顶部导航栏可滑动并选中放大
2019/12/05 Javascript
Vue项目移动端滚动穿透问题的实现
2020/05/19 Javascript
js实现查询商品案例
2020/07/22 Javascript
[00:36]DOTA2勇士令状莱恩声望物品——冥晶之厄展示
2018/05/25 DOTA
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
python 打印直角三角形,等边三角形,菱形,正方形的代码
2017/11/21 Python
Python用for循环实现九九乘法表
2018/05/31 Python
Python 中包/模块的 `import` 操作代码
2019/04/22 Python
使用Python OpenCV为CNN增加图像样本的实现
2019/06/10 Python
使用OpenCV实现仿射变换—平移功能
2019/08/29 Python
sklearn+python:线性回归案例
2020/02/24 Python
python如何获得list或numpy数组中最大元素对应的索引
2020/11/16 Python
Python修改DBF文件指定列
2020/12/19 Python
解决pytorch 数据类型报错的问题
2021/03/03 Python
致垒球运动员加油稿
2014/02/16 职场文书
投资合作协议书
2014/04/17 职场文书
酒店开业策划方案
2014/06/02 职场文书
2015年“七七卢沟桥事变”纪念活动总结
2015/03/24 职场文书
2015年客服工作总结范文
2015/04/02 职场文书
《跨越海峡的生命桥》教学反思
2016/02/18 职场文书