JavaScript中reduce()的用法


Posted in Javascript onMay 11, 2022

前言

过去有很长一段时间,我一直很难理解 reduce() 这个方法的具体用法,平时也很少用到它。事实上,如果你能真正了解它的话,其实在很多地方我们都可以用得上,那么今天我们就来简单聊聊JS中 reduce() 的用法。

一、语法

arr.reduce(function(prev,cur,index,arr){
...
}, init);

其中,

  • arr 表示原数组;
  • prev 表示上一次调用回调时的返回值,或者初始值 init;
  • cur 表示当前正在处理的数组元素;
  • index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
  • init 表示初始值。

看上去是不是感觉很复杂?没关系,只是看起来而已,其实常用的参数只有两个:prev 和 cur。接下来我们跟着实例来看看具体用法吧~

二、实例

先提供一个原始数组:

var arr = [3,9,4,3,6,0,9];

实现以下需求的方式有很多,其中就包含使用reduce()的求解方式,也算是实现起来比较简洁的一种吧。

1. 求数组项之和

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

由于传入了初始值0,所以开始时prev的值为0,cur的值为数组第一项3,相加之后返回值为3作为下一轮回调的prev值,然后再继续与下一个数组项相加,以此类推,直至完成所有数组项的和并返回。

2. 求数组项最大值

var max = arr.reduce(function (prev, cur) {
    return Math.max(prev,cur);
});

由于未传入初始值,所以开始时prev的值为数组第一项3,cur的值为数组第二项9,取两值最大值后继续进入下一轮回调。

3. 数组去重

var newArr = arr.reduce(function (prev, cur) {
    prev.indexOf(cur) === -1 && prev.push(cur);
    return prev;
},[]);

实现的基本原理如下:

① 初始化一个空数组

② 将需要去重处理的数组中的第1项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中

③ 将需要去重处理的数组中的第2项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中

④ ……

⑤ 将需要去重处理的数组中的第n项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中

⑥ 将这个初始化数组返回

三、其他相关方法

1. reduceRight()

该方法用法与reduce()其实是相同的,只是遍历的顺序相反,它是从数组的最后一项开始,向前遍历到第一项。

2. forEach()、map()、every()、some()和filter()

详情请戳→简述forEach()、map()、every()、some()和filter()的用法

重点总结:

reduce() 是数组的归并方法,与forEach()、map()、filter()等迭代方法一样都会对数组每一项进行遍历,但是reduce() 可同时将前面数组项遍历产生的结果与当前遍历项进行运算,这一点是其他迭代方法无法企及的

先看w3c语法

array.reduce(function(total, currentValue, currentIndex, arr), initialValue);
/*
  total: 必需。初始值, 或者计算结束后的返回值。
  currentValue: 必需。当前元素。
  currentIndex: 可选。当前元素的索引;                     
  arr: 可选。当前元素所属的数组对象。
  initialValue: 可选。传递给函数的初始值,相当于total的初始值。
*/

常见用法

数组求和

const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num);
<!-- 设定初始值求和 -->
const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num, 10);  // 以10为初始值求和
<!-- 对象数组求和 -->
var result = [
  { subject: 'math', score: 88 },
  { subject: 'chinese', score: 95 },
  { subject: 'english', score: 80 }
];
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, 0); 
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, -10);  // 总分扣除10分

数组最大值

const a = [23,123,342,12];
const max = a.reduce(function(pre,cur,inde,arr){return pre>cur?pre:cur;}); // 342

进阶用法

数组对象中的用法

<!-- 比如生成“老大、老二和老三” -->
const objArr = [{name: '老大'}, {name: '老二'}, {name: '老三'}];
const res = objArr.reduce((pre, cur, index, arr) => {
  if (index === 0) {
    return cur.name;
  }
  else if (index === (arr.length - 1)) {
    return pre + '和' + cur.name;
  }
  else {
    return pre + '、' + cur.name;
  }
}, '');

求字符串中字母出现的次数

const str = 'sfhjasfjgfasjuwqrqadqeiqsajsdaiwqdaklldflas-cmxzmnha';
const res = str.split('').reduce((accumulator, cur) => {accumulator[cur] ? accumulator[cur]++ : accumulator[cur] = 1; return accumulator;}, {});

数组转数组

<!-- 按照一定的规则转成数组 -->
var arr1 = [2, 3, 4, 5, 6]; // 每个值的平方
var newarr = arr1.reduce((accumulator, cur) => {accumulator.push(cur * cur); return accumulator;}, []);

数组转对象

<!-- 按照id 取出stream -->
var streams = [{name: '技术', id: 1}, {name: '设计', id: 2}];
var obj = streams.reduce((accumulator, cur) => {accumulator[cur.id] = cur; return accumulator;}, {});

高级用法

多维的叠加执行操作

<!-- 各科成绩占比重不一样, 求结果 -->
var result = [
  { subject: 'math', score: 88 },
  { subject: 'chinese', score: 95 },
  { subject: 'english', score: 80 }
];
var dis = {
    math: 0.5,
    chinese: 0.3,
    english: 0.2
};
var res = result.reduce((accumulator, cur) => dis[cur.subject] * cur.score + accumulator, 0);
var prices = [{price: 23}, {price: 45}, {price: 56}];
var rates = {
  us: '6.5',
  eu: '7.5',
};
var initialState = {usTotal:0, euTotal: 0};
var res = prices.reduce((accumulator, cur1) => Object.keys(rates).reduce((prev2, cur2) => {
  console.log(accumulator, cur1, prev2, cur2);
  accumulator[`${cur2}Total`] += cur1.price * rates[cur2];
  return accumulator;
}, {}), initialState);

var manageReducers = function() {
  return function(state, item) {
    return Object.keys(rates).reduce((nextState, key) => {
        state[`${key}Total`] += item.price * rates[key];
        return state;
      }, {});
  }
};
var res1= prices.reduce(manageReducers(), initialState);

扁平一个二维数组

var arr = [[1, 2, 8], [3, 4, 9], [5, 6, 10]];
var res = arr.reduce((x, y) => x.concat(y), []);

对象数组去重

const hash = {};
  chatlists = chatlists.reduce((obj, next: Object) => {
    const hashId = `${next.topic}_${next.stream_id}`;
    if (!hash[hashId]) {
      hash[`${next.topic}_${next.stream_id}`] = true;
      obj.push(next);
    }
    return obj;
  }, []);

compose函数

redux compose源码实现

function compose(...funs) {
    if (funs.length === 0) {
        return arg => arg;
    }
    if (funs.length === 1) {
       return funs[0];
    }
    return funs.reduce((a, b) => (...arg) => a(b(...arg)))

}

总结

到此这篇关于JavaScript中reduce()用法实例的文章就介绍到这了!


Tags in this post...

Javascript 相关文章推荐
使用正则替换变量
May 05 Javascript
Javascript 阻止javascript事件冒泡,获取控件ID值
Jun 27 Javascript
简单实例处理url特殊符号&amp;处理(2种方法)
Apr 02 Javascript
jquery 字符串切割函数substring的用法说明
Feb 11 Javascript
window.open()详解及浏览器兼容性问题示例探讨
May 29 Javascript
JS判断移动端访问设备并加载对应CSS样式
Jun 13 Javascript
微信浏览器内置JavaScript对象WeixinJSBridge使用实例
May 25 Javascript
Javascript Function.prototype.bind详细分析
Dec 29 Javascript
详解node.js平台下Express的session与cookie模块包的配置
Apr 26 Javascript
使用vue和datatables进行表格的服务器端分页实例代码
Jun 07 Javascript
详解vue axios用post提交的数据格式
Aug 07 Javascript
jQuery使用ajax传递json对象到服务端及contentType的用法示例
Mar 12 jQuery
处理canvas绘制图片模糊问题
介绍一下28个JS常用数组方法
May 06 #Javascript
VUE解决跨域问题Access to XMLHttpRequest at
js判断两个数组相等的5种方法
May 06 #Javascript
vue使用watch监听属性变化
Apr 30 #Vue.js
vue-cli3.x配置全局的scss的时候报错问题及解决
vue项目如何打包之项目打包优化(让打包的js文件变小)
You might like
使用PHP实现蜘蛛访问日志统计
2013/07/05 PHP
php版小黄鸡simsimi聊天机器人接口分享
2014/01/26 PHP
/etc/php-fpm.d/www.conf 配置注意事项
2017/02/04 PHP
PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
2019/04/27 PHP
PHP连接SQL server数据库测试脚本运行实例
2020/08/24 PHP
php框架知识点的整理和补充
2021/03/01 PHP
jQuery Validation插件remote验证方式的Bug解决
2010/07/01 Javascript
js获得鼠标的坐标值的方法
2013/03/13 Javascript
html页面显示年月日时分秒和星期几的两种方式
2013/08/20 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
2014/01/15 Javascript
AngularJS语法详解(续)
2015/01/23 Javascript
详解JavaScript中jQuery和Ajax以及JSONP的联合使用
2015/08/13 Javascript
详解AngularJS中自定义过滤器
2015/12/28 Javascript
深入理解js函数的作用域与this指向
2016/05/28 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
2016/06/23 Javascript
js实现图片360度旋转
2017/01/22 Javascript
利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层
2017/03/15 Javascript
angular中实现控制器之间传递参数的方式
2017/04/24 Javascript
微信小程序使用input组件实现密码框功能【附源码下载】
2017/12/11 Javascript
深入理解ES6之数据解构的用法
2018/01/13 Javascript
iview的table组件自带的过滤器实现
2019/07/12 Javascript
深入了解Vue3模板编译原理
2020/11/19 Vue.js
[39:08]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第一场 12.12
2020/12/16 DOTA
Python3.x中自定义比较函数
2015/04/24 Python
Python实现二分查找与bisect模块详解
2017/01/13 Python
python中列表和元组的区别
2017/12/18 Python
python远程连接服务器MySQL数据库
2018/07/02 Python
详解Python Qt的窗体开发的基本操作
2019/07/14 Python
python requests证书问题解决
2019/09/05 Python
Android本地应用打开方法——通过html5写连接
2016/03/11 HTML / CSS
美国在线家居装饰店:Belle&June
2018/10/24 全球购物
《临死前的严监生》教学反思
2014/02/13 职场文书
商场客服专员岗位职责
2014/06/13 职场文书
党的群众路线教育实践活动总结材料
2014/10/30 职场文书
学校教师培训工作总结
2015/10/14 职场文书
《平行四边形的面积》教学反思
2016/02/16 职场文书