详解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 相关文章推荐
JS中剪贴板兼容性、判断复制成功或失败
Mar 09 Javascript
Mootools 1.2教程 输入过滤第二部分(字符串)
Sep 15 Javascript
javascript下string.format函数补充
Aug 24 Javascript
JavaScript字符串String和Array操作的有趣方法
Dec 18 Javascript
jquery简单图片切换显示效果实现方法
Jan 14 Javascript
JS实现浏览器状态栏文字从右向左弹出效果代码
Oct 27 Javascript
JS修改地址栏参数实例代码
Jun 14 Javascript
原生Javascript和jQuery做轮播图简单例子
Oct 11 Javascript
详解使用element-ui table组件的筛选功能的一个小坑
Nov 02 Javascript
移动端手指操控左右滑动的菜单
Sep 08 Javascript
详解JS深拷贝与浅拷贝
Aug 04 Javascript
详解TypeScript的基础类型
Feb 18 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
解析dedeCMS验证码的实现代码
2013/06/07 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
2017/12/21 PHP
实现php删除链表中重复的结点
2018/09/27 PHP
JavaScript窗口功能指南之在窗口中书写内容
2006/07/21 Javascript
用JavaScript对JSON进行模式匹配 (Part 2 - 实现)
2010/07/17 Javascript
分享20款好玩的jQuery游戏
2011/04/17 Javascript
functional继承模式 摘自javascript:the good parts
2011/06/20 Javascript
jquery随意添加移除html的实现代码
2011/06/21 Javascript
一些老手都不一定知道的JavaScript技巧
2014/05/06 Javascript
jQuery中ready事件用法实例
2015/01/19 Javascript
jquery通过closest选择器修改上级元素的方法
2015/03/17 Javascript
jquery控制表单输入框显示默认值的方法
2015/05/22 Javascript
浅谈jQuery中height与width
2015/07/06 Javascript
Angular 4.x中表单Reactive Forms详解
2017/04/25 Javascript
浅谈layer弹出层按钮颜色修改方法
2019/09/11 Javascript
python实现从web抓取文档的方法
2014/09/26 Python
python和shell实现的校验IP地址合法性脚本分享
2014/10/23 Python
Django中利用filter与simple_tag为前端自定义函数的实现方法
2017/06/15 Python
在PyCharm导航区中打开多个Project的关闭方法
2019/01/17 Python
Python生成指定数量的优惠码实操内容
2019/06/18 Python
Django 实现admin后台显示图片缩略图的例子
2019/07/28 Python
win10安装tensorflow-gpu1.8.0详细完整步骤
2020/01/20 Python
Python3.7在anaconda里面使用IDLE编译器的步骤详解
2020/04/29 Python
Python 列表推导式需要注意的地方
2020/10/23 Python
selenium自动化测试入门实战
2020/12/21 Python
详解HTML5 Canvas绘制时指定颜色与透明度的方法
2016/03/25 HTML / CSS
网络优化专员求职信
2014/05/04 职场文书
手术室护士个人总结
2015/02/13 职场文书
2015毕业实习推荐信
2015/03/23 职场文书
建筑技术负责人岗位职责
2015/04/13 职场文书
2015年办公室个人工作总结
2015/04/20 职场文书
2015年仓管员工作总结
2015/04/21 职场文书
公司聚餐通知
2015/04/22 职场文书
2015年重阳节活动主持词
2015/07/30 职场文书
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
2021/05/21 Redis