JS中concat、reduce与find组合使用逻辑解析求助
代码逻辑解析:concat + reduce 实现数组按ID去重
先看你给出的完整代码:
var item1 = [ {"id":1,"b":"first"}, {"id":2,"b":"second"} ]; var item2 = [ {"id":3,"b":"third", "c":true}, {"id":1,"b":"fourth", "c":true}, {"id":2,"b":"fivth", "c":true}, {"id":4,"b":"frr", "c":true} ]; var res = item1.concat(item2).reduce((aggr, el)=>{ if(!aggr.find(item=>item.id==el.id)) return [...aggr, el]; else return aggr },[])
整体功能
这段代码的核心作用是:合并两个数组后,按照id字段去重,保留每个id第一次出现的元素。
分步解析
item1.concat(item2)
你已经理解这一步:把item1和item2合并成一个新数组,顺序是item1的元素在前,item2的在后,合并后的数组为:[ {"id":1,"b":"first"}, {"id":2,"b":"second"}, {"id":3,"b":"third", "c":true}, {"id":1,"b":"fourth", "c":true}, {"id":2,"b":"fivth", "c":true}, {"id":4,"b":"frr", "c":true} ]reduce的基础工作流程reduce以空数组[]作为初始值(也就是第一次循环时aggr是空数组),然后依次遍历合并后的每个元素el,每次循环根据条件决定是否把当前el加入累加器aggr。核心疑惑:
!aggr.find(item=>item.id==el.id)
拆解成两部分看:aggr.find(item=>item.id==el.id):find方法会遍历当前的aggr数组,找第一个id和当前el.id相等的元素。如果找到,就返回这个元素;如果找不到,返回undefined。- 前面的
!(逻辑非运算符):把find的结果转换成布尔值,用来判断条件:- 如果
find找到了匹配的元素(返回一个对象,属于JavaScript里的“真值”),!会把它变成false,条件不成立,进入else分支,直接返回原aggr——也就是不把当前el加入累加器(因为这个id已经存在了)。 - 如果
find没找到匹配的元素(返回undefined,属于“假值”),!会把它变成true,条件成立,返回[...aggr, el]——也就是把当前el添加到累加器的末尾(这个id是第一次出现)。
- 如果
遍历过程示例(更直观理解)
我们跟着循环走一遍:
- 第1次循环:
el = {"id":1,"b":"first"},aggr是空数组。find找不到id=1的元素,返回undefined,!undefined为true,所以aggr变成[{"id":1,"b":"first"}]。 - 第2次循环:
el = {"id":2,"b":"second"},aggr里没有id=2的元素,!undefined为true,aggr变成[{"id":1,"b":"first"}, {"id":2,"b":"second"}]。 - 第3次循环:
el = {"id":3,"b":"third", "c":true},aggr里没有id=3的元素,!undefined为true,aggr新增这个元素,现在有3个元素。 - 第4次循环:
el = {"id":1,"b":"fourth", "c":true},aggr里已有id=1的元素,find返回该元素,!元素为false,直接返回原aggr,不添加当前元素。 - 第5次循环:
el = {"id":2,"b":"fivth", "c":true},aggr里已有id=2的元素,!元素为false,返回原aggr,不添加。 - 第6次循环:
el = {"id":4,"b":"frr", "c":true},aggr里没有id=4的元素,!undefined为true,新增这个元素。
最终res的结果是:
[ {"id":1,"b":"first"}, {"id":2,"b":"second"}, {"id":3,"b":"third", "c":true}, {"id":4,"b":"frr", "c":true} ]
内容的提问来源于stack exchange,提问作者Still_Learning
相关产品推荐
相关产品推荐

