JS数组Reduce的妙用,收藏等于学会!

开发 前端
说到处理数组的方法,想必大家都不陌生了,今天我们一起来学习下理数组常见场景下的方法。

[[419162]]

本文转载自微信公众号「前端发现」,作者前端发现者。转载本文请联系前端发现公众号。

说到处理数组的方法,想必大家都不陌生了,今天我们一起来学习下理数组常见场景下的方法。

首先来看看 reduce 方法可以传入哪些参数

  1. function(pre,cur,index,arr) 
  • pre:必需,初始值或计算结束后的返回值
  • cur:非必需,当前处理的元素
  • index:非必需,当前处理元素的索引
  • arr:非必需,当前元素所属的数组对象

直接看看

  1. const list = [1,2,3,4,5] 
  2. const result = list.reduce(function (pre, cur, index, arr) { 
  3.   console.log('pre:' + pre, 'cur:' + cur, 'index:' + index
  4.   return pre + cur 
  5. }) 
  6. console.log(result) 
  7.  
  8. // => pre:1 cur:2 index:1 
  9. // => pre:3 cur:3 index:2 
  10. // => pre:6 cur:4 index:3 
  11. // => pre:10 cur:5 index:4 
  12. // => 15 

可以看到,第一轮pre的值是数组的第一个值,然后当前处理元素直接是元素的第二个数据,索引是数组的1。第二轮的pre就是第一次逻辑处理 return pre + cur 返回的结果(即3)。以此类推...共循环4轮。

再来看个相乘的处理逻辑的:

  1. const list = [1,2,3,4,5] 
  2. const result = list.reduce(function (pre, cur, index, arr) { 
  3.   console.log('pre:' + pre, 'cur:' + cur, 'index:' + index
  4.   return pre * cur 
  5. }) 
  6. console.log(result) 
  7.  
  8. // => pre:1 cur:2 index:1 
  9. // => pre:2 cur:3 index:2 
  10. // => pre:6 cur:4 index:3 
  11. // => pre:24 cur:5 index:4 
  12. // => 120 

看着这么复杂,能举个再简单的例子吗?别问,问就是有!

  1. const result = list.reduce((pre, cur) => pre + cur) 
  2. console.log(result) // => 15 

简单后再来个高级点的尝鲜下。

数组去重

将数组传输之前,我们先来了解下 reduce 的另外一个,即 initialValue。它是代表传递给函数的初始值,「可以理解为给pre设置了默认的值」。

  1. const list = [1,1,3,5,5,7,9] 
  2. let arr = list.reduce((pre,cur)=>{ 
  3.   if(!pre.includes(cur)){ 
  4.     return pre.concat(cur) 
  5.   }else
  6.     return pre 
  7.   } 
  8. },[]) // => 给pre设置默认的空数组[] 
  9. console.log(arr) // => [1, 3, 5, 7, 9] 

可以看到list数组的长度为7,共循环7次(设置默认的空数组,导致cur第一轮是数组的第一个数据)。每循环一次就判断pre数组里存不存在当前循环的元素,若不存在则加入到pre数组去,否则就直接退出当前循环。

数组二维转一维

  1. let arr = [1,2,[4, 6], [1, 6], [2, 2]] 
  2. let newArr = arr.reduce((pre,cur)=>{ 
  3.   return pre.concat(cur) 
  4. },[]) 
  5. console.log(newArr) // => [1, 2, 4, 6, 1, 6, 2, 2] 

这里其实也就是利用了数组的 concat 方法,跟上面的使用也是大同小异,理顺一下就可以理解的了。

数组多维转一维

  1. let arr = [1, 2, [4, 6], [1, 6, [3, 6]], [1, [3, 4, [1, 2]], [2, 2]]] 
  2. const newArr = (arr) => { 
  3.   return arr.reduce((pre, cur) => { 
  4.     return pre.concat(Array.isArray(cur) ? newArr(cur) : cur) 
  5.   }, []) 
  6. console.log(newArr(arr)) // => [1, 2, 4, 6, 1, 6, 3, 6, 1, 3, 4, 1, 2, 2, 2] 

这里使用了 三目运算 、 concat 数据拼接 、递归 的思路完成。先判断当前处理的元素(有可能是数组)是不是数组(Array.isArray(cur)),如果是再次执行newArr,否则就直接处理当前元素,即将cur拼接进之前处理的数组中。

计算元素出现个数

讲解这个之前我们先来回忆下for...in的用法:

for...in 声明用于对数组或者对象的属性进行循环/迭代操作。

直接上

  1. var arr = ['张三','李四','王五']     
  2. for (let x in arr)   
  3. {   
  4.   console.log(x) 
  5.   // => 张三 
  6.   // => 李四 
  7.   // => 王五 
  8. }   

可以看到当arr为数组时 x 相当于 for 循环的?? 标

那当arr为对象呢?

  1. const obj = {   
  2.   name"张三",   
  3.   age: 18,   
  4.   height: "180"   
  5. }   
  6. for(let key in obj){   
  7.   console.log(key)  
  8.   // => name 
  9.   // => age 
  10.   // => height 
  11. }   

可以看到当循环的“对象”是对象时,循环的单项就是对象的属性。

所以我们可以根据这个特性来判断对象是否为数组/对象的元素/属性。

  1. // 数组时判断下标 
  2. let arr = ["a","b","2","3"]  
  3. console.log("b" in arr) // => false 
  4. console.log(2 in arr) // => true 
  5.  
  6. // 对象时判断属性 
  7. let obj = {a:"a",b:"b",c:"2",d:"3"}  
  8. console.log("b" in obj) // => true 
  9. console.log(2 in obj) // => false 

好的,回忆完这些知识,我们来看看怎么完成这个需求

  1. let names = ['张三''李四''张三''王五''王五''王五'
  2. let total = names.reduce((pre,cur)=>{ 
  3.   if(cur in pre){ 
  4.     pre[cur]++ 
  5.     console.log("判断为真:"
  6.     console.log(pre) 
  7.   }else
  8.     pre[cur] = 1 
  9.     console.log("判断为假:"
  10.     console.log(pre) 
  11.   } 
  12.   return pre 
  13. },{}) 
  14. console.log(total); // => {张三: 2, 李四: 1, 王五: 3} 

首先先传入一个{}对象,说明初始的pre为{}。那么第一轮判断if的时候就变成 '张三' in {} 很明显此时判断条件是 false 。所以就执行 else 里面的逻辑后变成:{'张三':1}。第二轮时 李四 也是如此。当第三轮时再次遇到“张三”,此时对象是 {'张三':1,'李四':1} ,所以if判断是 true ,所以张三直接+1。来看看打印情况:

  1. 判断为假: 
  2. // => {张三: 1} 
  3. 判断为假: 
  4. // => {张三: 1, 李四: 1} 
  5. 判断为真: 
  6. // => {张三: 2, 李四: 1} 
  7. 判断为假: 
  8. // => {张三: 2, 李四: 1, 王五: 1} 
  9. 判断为真: 
  10. // => {张三: 2, 李四: 1, 王五: 2} 
  11. 判断为真: 
  12. // => {张三: 2, 李四: 1, 王五: 3} 

属性求和

  1. const list = [ 
  2.   { 
  3.     name'张三'
  4.     age: 18 
  5.   }, 
  6.   { 
  7.     name'李四'
  8.     age: 20 
  9.   }, 
  10.   { 
  11.     name'王五'
  12.     age: 22 
  13.   } 
  14. let total = list.reduce((pre, cur) => { 
  15.   console.log(cur)  
  16.   // => {name'张三', age: 18} 
  17.   // => {name'李四', age: 20} 
  18.   // => {name'王五', age: 22} 
  19.   return cur.age + pre 
  20. }, 0) 
  21. console.log(total) // => 60 

如此是不是省了使用 map 去求和呢?更简便可以这么写:

  1. let total = list.reduce((pre, cur) => cur.age + pre, 0) 

到此,今日的前端发现知识分享就到此结束了。

 

责任编辑:武晓燕 来源: 前端发现
相关推荐

2023-02-01 08:31:48

2011-07-20 17:54:02

C++

2023-01-09 18:15:21

数组Python类型

2022-10-21 08:02:40

reduce​初始值循环

2021-09-29 06:03:37

JavaScriptreduce() 前端

2024-04-07 08:15:13

Go语言工具

2021-03-22 06:28:44

reducemap函数

2009-10-19 11:26:08

Scala循环数组

2020-02-13 18:05:18

数组reduce前端

2022-06-01 08:12:32

JS类数组对象

2022-07-06 10:04:45

JavaScript数组前端

2023-05-08 08:11:55

KubernetesK8S

2010-09-08 16:26:26

SQL循环语句

2023-08-01 09:46:57

虚拟键盘API

2021-03-05 07:45:59

JSreducemap

2010-09-26 09:50:36

SQL Where子句

2023-11-27 19:35:01

C++extern

2019-11-11 21:24:42

HadoopHbase分布式

2010-09-10 15:16:51

CSSdisplay

2021-02-01 07:55:37

JS 数组元素
点赞
收藏

51CTO技术栈公众号