百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

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

liuian 2025-03-13 17:16 38 浏览


作者:前端发现者来源:前端发现

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

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

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

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

直接看看

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

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

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

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

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

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

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

数组去重

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

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

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

数组二维转一维

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

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

数组多维转一维

let arr = [1, 2, [4, 6], [1, 6, [3, 6]], [1, [3, 4, [1, 2]], [2, 2]]] 
const newArr = (arr) => { 
  return arr.reduce((pre, cur) => { 
    return pre.concat(Array.isArray(cur) ? newArr(cur) : cur) 
  }, []) 
} 
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 声明用于对数组或者对象的属性进行循环/迭代操作。

直接上

var arr = ['张三','李四','王五']     
for (let x in arr)   
{   
  console.log(x) 
  // => 张三 
  // => 李四 
  // => 王五 
}

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

那当arr为对象呢?

const obj = {   
  name: "张三",   
  age: 18,   
  height: "180"   
}   
for(let key in obj){   
  console.log(key)  
  // => name 
  // => age 
  // => height 
}

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

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

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

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

let names = ['张三', '李四', '张三', '王五', '王五', '王五'] 
let total = names.reduce((pre,cur)=>{ 
  if(cur in pre){ 
    pre[cur]++ 
    console.log("判断为真:") 
    console.log(pre) 
  }else{ 
    pre[cur] = 1 
    console.log("判断为假:") 
    console.log(pre) 
  } 
  return pre 
},{}) 
console.log(total); // => {张三: 2, 李四: 1, 王五: 3}

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

判断为假: 
// => {张三: 1} 
判断为假: 
// => {张三: 1, 李四: 1} 
判断为真: 
// => {张三: 2, 李四: 1} 
判断为假: 
// => {张三: 2, 李四: 1, 王五: 1} 
判断为真: 
// => {张三: 2, 李四: 1, 王五: 2} 
判断为真: 
// => {张三: 2, 李四: 1, 王五: 3}

属性求和

const list = [ 
  { 
    name: '张三', 
    age: 18 
  }, 
  { 
    name: '李四', 
    age: 20 
  }, 
  { 
    name: '王五', 
    age: 22 
  } 
] 
let total = list.reduce((pre, cur) => { 
  console.log(cur)  
  // => {name: '张三', age: 18} 
  // => {name: '李四', age: 20} 
  // => {name: '王五', age: 22} 
  return cur.age + pre 
}, 0) 
console.log(total) // => 60

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

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

相关推荐

驱动网卡(怎么从新驱动网卡)
驱动网卡(怎么从新驱动网卡)

网卡一般是指为电脑主机提供有线无线网络功能的适配器。而网卡驱动指的就是电脑连接识别这些网卡型号的桥梁。网卡只有打上了网卡驱动才能正常使用。并不是说所有的网卡一插到电脑上面就能进行数据传输了,他都需要里面芯片组的驱动文件才能支持他进行数据传输...

2026-01-30 00:37 liuian

win10更新助手装系统(微软win10更新助手)

1、点击首页“系统升级”的按钮,给出弹框,告诉用户需要上传IMEI码才能使用升级服务。同时给出同意和取消按钮。华为手机助手2、点击同意,则进入到“系统升级”功能华为手机助手华为手机助手3、在检测界面,...

windows11专业版密钥最新(windows11专业版激活码永久)

 Windows11专业版的正版密钥,我们是对windows的激活所必备的工具。该密钥我们可以通过微软商城或者通过计算机的硬件供应商去购买获得。获得了windows11专业版的正版密钥后,我...

手机删过的软件恢复(手机删除过的软件怎么恢复)
手机删过的软件恢复(手机删除过的软件怎么恢复)

操作步骤:1、首先,我们需要先打开手机。然后在许多图标中找到带有[文件管理]文本的图标,然后单击“文件管理”进入页面。2、进入页面后,我们将在顶部看到一行文本:手机,最新信息,文档,视频,图片,音乐,收藏,最后是我们正在寻找的[更多],单击...

2026-01-29 23:55 liuian

一键ghost手动备份系统步骤(一键ghost 备份)

  步骤1、首先把装有一键GHOST装系统的U盘插在电脑上,然后打开电脑马上按F2或DEL键入BIOS界面,然后就选择BOOT打USDHDD模式选择好,然后按F10键保存,电脑就会马上重启。  步骤...

怎么创建局域网(怎么创建局域网打游戏)

  1、购买路由器一台。进入路由器把dhcp功能打开  2、购买一台交换机。从路由器lan端口拉出一条网线查到交换机的任意一个端口上。  3、两台以上电脑。从交换机任意端口拉出网线插到电脑上(电脑设置...

精灵驱动器官方下载(精灵驱动手机版下载)

是的。驱动精灵是一款集驱动管理和硬件检测于一体的、专业级的驱动管理和维护工具。驱动精灵为用户提供驱动备份、恢复、安装、删除、在线更新等实用功能。1、全新驱动精灵2012引擎,大幅提升硬件和驱动辨识能力...

一键还原系统步骤(一键还原系统有哪些)

1、首先需要下载安装一下Windows一键还原程序,在安装程序窗口中,点击“下一步”,弹出“用户许可协议”窗口,选择“我同意该许可协议的条款”,并点击“下一步”。  2、在弹出的“准备安装”窗口中,可...

电脑加速器哪个好(电脑加速器哪款好)

我认为pp加速器最好用,飞速土豆太懒,急速酷六根本不工作。pp加速器什么网页都加速,太任劳任怨了!以上是个人观点,具体性能请自己试。ps:我家电脑性能很好。迅游加速盒子是可以加速电脑的。因为有过之...

任何u盘都可以做启动盘吗(u盘必须做成启动盘才能装系统吗)

是的,需要注意,U盘的大小要在4G以上,最好是8G以上,因为启动盘里面需要装系统,内存小的话,不能用来安装系统。内存卡或者U盘或者移动硬盘都可以用来做启动盘安装系统。普通的U盘就可以,不过最好U盘...

u盘怎么恢复文件(u盘文件恢复的方法)

开360安全卫士,点击上面的“功能大全”。点击文件恢复然后点击“数据”下的“文件恢复”功能。选择驱动接着选择需要恢复的驱动,选择接入的U盘。点击开始扫描选好就点击中间的“开始扫描”,开始扫描U盘数据。...

系统虚拟内存太低怎么办(系统虚拟内存占用过高什么原因)

1.检查系统虚拟内存使用情况,如果发现有大量的空闲内存,可以尝试释放一些不必要的进程,以释放内存空间。2.如果系统虚拟内存使用率较高,可以尝试增加系统虚拟内存的大小,以便更多的应用程序可以使用更多...

剪贴板权限设置方法(剪贴板访问权限)
剪贴板权限设置方法(剪贴板访问权限)

1、首先打开iphone手机,触碰并按住单词或图像直到显示选择选项。2、其次,然后选取“拷贝”或“剪贴板”。3、勾选需要的“权限”,最后选择开启,即可完成苹果剪贴板权限设置。仅参考1.打开苹果手机设置按钮,点击【通用】。2.点击【键盘】,再...

2026-01-29 21:37 liuian

平板系统重装大师(平板重装win系统)

如果你的平板开不了机,但可以连接上电脑,那就能好办,楼主下载安装个平板刷机王到你的个人电脑上,然后连接你的平板,平板刷机王会自动识别你的平板,平板刷机王上有你平板的我刷机包,楼主点击下载一个,下载完成...

联想官网售后服务网点(联想官网售后服务热线)

联想3c服务中心是联想旗下的官方售后,是基于互联网O2O模式开发的全新服务平台。可以为终端用户提供多品牌手机、电脑以及其他3C类产品的维修、保养和保险服务。根据客户需求层次,联想服务针对个人及家庭客户...