在forEach循环中过滤数组:移除两数组id匹配的元素
代码失效的核心原因
filter方法不会修改原数组,只会返回符合过滤条件的新数组:你之前在forEach循环里调用filter后,既没有把返回的新数组赋值给任何变量,也没有替换原数组,循环跑完原needToFilter完全没有变化- 最后打印的
users变量从未定义,运行时会直接报引用错误,根本拿不到过滤结果 - 原嵌套循环的逻辑本身效率极低:每遍历一个已点赞用户,就全量扫一遍
needToFilter,就算存了返回值,多次嵌套过滤的结果也不符合预期
可正常运行的实现方案
方案1:基础数组匹配实现
先把已点赞的用户id提取成单独的扁平数组,再对待过滤数组做一次单轮遍历即可,逻辑直白易读,适合小数据量场景:
const likedIds = likedUsers.map(item => item.id) const filteredResult = needToFilter.filter(item => !likedIds.includes(item.id))
方案2:Set匹配实现(最终采用方案)
提前把已点赞的id存进Set结构,利用Sethas方法的O(1)查找复杂度,大幅提升大数据量下的运行效率,是综合性能最优的实现之一:
const likedIdSet = new Set(likedUsers.map(item => item.id)) const filteredResult = needToFilter.filter(item => !likedIdSet.has(item.id))
执行完后filteredResult的值就是[{id:"3",userInfo:"info"}],完全符合预期。
方案3:直接修改原数组实现
如果业务场景要求不能生成新数组,要直接修改原needToFilter,可以倒序遍历数组后用splice删除匹配项,避免正序删除时的索引错位问题:
const likedIdSet = new Set(likedUsers.map(item => item.id)) // 从数组末尾向前遍历,删除匹配项不会打乱前面元素的索引 for (let i = needToFilter.length - 1; i >= 0; i--) { if (likedIdSet.has(needToFilter[i].id)) { needToFilter.splice(i, 1) } }
内容的提问来源于stack exchange,提问作者Deniz Firat
相关产品推荐
相关产品推荐

