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 相关文章推荐
jQuery表单验证插件formValidator(改进版)
Feb 03 Javascript
Jquery实现自定义tooltip示例代码
Feb 12 Javascript
jquery插件开发之实现md5插件
Mar 17 Javascript
node.js中的fs.readSync方法使用说明
Dec 17 Javascript
Bootstrap 附加导航(Affix)插件实例详解
Jun 01 Javascript
jQuery 移动端拖拽(模块化开发,触摸事件,webpack)
Oct 28 Javascript
深入理解 JavaScript 中的 JSON
Apr 06 Javascript
JavaScript使用Ajax上传文件的示例代码
Aug 10 Javascript
JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】
Feb 06 Javascript
3种vue路由传参的基本模式
Feb 22 Javascript
详解Vue.js自定义tipOnce指令用法实例
Dec 19 Javascript
es6中使用map简化复杂条件判断操作实例详解
Feb 19 Javascript
处理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实现获取第一个中文首字母并进行排序的方法
2017/05/09 PHP
PHP实现绘制二叉树图形显示功能详解【包括二叉搜索树、平衡树及红黑树】
2017/11/16 PHP
如何在PHP环境中使用ProtoBuf数据格式
2020/06/19 PHP
ASP SQL防注入的方法
2008/12/25 Javascript
Javascript 获取链接(url)参数的方法
2009/02/15 Javascript
js 图片等比例缩放代码
2010/05/13 Javascript
SpringMVC restful 注解之@RequestBody进行json与object转换
2015/12/10 Javascript
谈一谈javascript中继承的多种方式
2016/02/19 Javascript
js数组操作方法总结(必看篇)
2016/11/22 Javascript
jQuery插件扩展实例【添加回调函数】
2016/11/26 Javascript
BootStrap 实现各种样式的进度条效果
2016/12/07 Javascript
快速实现JS图片懒加载(可视区域加载)示例代码
2017/01/04 Javascript
vue 使用自定义指令实现表单校验的方法
2018/08/28 Javascript
vue 使用html2canvas将DOM转化为图片的方法
2018/09/11 Javascript
微信小程序 WXML节点信息查询详解
2019/07/29 Javascript
如何使用proxy实现一个简单完整的MVVM库的示例代码
2019/09/17 Javascript
Paypal支付不完全指北
2020/06/04 Javascript
Python中使用PDB库调试程序
2015/04/05 Python
Python实现批量下载文件
2015/05/17 Python
给Python入门者的一些编程建议
2015/06/15 Python
python django框架中使用FastDFS分布式文件系统的安装方法
2019/06/10 Python
解决django-xadmin列表页filter关联对象搜索问题
2019/11/15 Python
使用python-opencv读取视频,计算视频总帧数及FPS的实现
2019/12/10 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
2020/02/28 Python
CSS3中的@keyframes关键帧动画的选择器绑定
2016/06/13 HTML / CSS
html5标记文字_动力节点Java学院整理
2017/07/11 HTML / CSS
详解HTML5之pushstate、popstate操作history,无刷新改变当前url
2017/03/15 HTML / CSS
HTML5拖拽文件上传的示例代码
2021/03/04 HTML / CSS
葡萄牙鞋子品牌:Fair
2016/12/10 全球购物
阿联酋航空官方网站:Emirates
2017/10/17 全球购物
介绍一下Python中webbrowser的用法
2013/05/07 面试题
广告语设计及教案
2014/03/21 职场文书
庆国庆国旗下讲话稿2014
2014/09/21 职场文书
群众路线剖析材料(四风)
2014/11/05 职场文书
工程项目经理岗位职责
2015/02/02 职场文书
广告业务员岗位职责
2015/02/13 职场文书