JavaScript中如何复制数组指定值到另一数组 实现去重更新qty
代码问题分析
你的逻辑出现重复添加的根本原因是内层循环的判断、分支控制、遍历对象都存在错误,具体问题如下:
- 内层循环没有完成全量匹配就触发分支逻辑:只要当前遍历到的j位置元素id和arr1[i]不匹配,就立刻进入else分支尝试push元素,执行完push直接break终止内层循环,根本不会检查arr2中j之后的元素是否存在同id项。
- 新增逻辑缺少"元素不存在"的全局校验:你错误地将"当前j位置元素id不匹配"等同于"整个数组中不存在该id的元素",只要某一个位置不匹配就新增,完全没有遍历完数组确认是否真的没有重复项。
- 内层循环遍历对象错误:你内层循环遍历的是原始的arr2数组,而不是拷贝后的newArray,如果循环过程中已经往newArray里新增过同id元素,内层循环根本检测不到,会进一步导致重复添加。
- 无效判断太多:不需要在内层循环的每个分支都重复判断arr1[i].checked的值,外层循环一开始就可以跳过checked为false的元素,减少不必要的内层遍历。
修正代码
先给和你原有写法最接近的双层循环版本,改动最小,方便你对照理解:
const handleAdd = () => { const newArray = [...arr2] for (let i = 0; i < arr1.length; i++) { const currentItem = arr1[i] // 未勾选的元素直接跳过,不做后续处理 if (!currentItem.checked) continue let hasExisted = false // 遍历整个结果数组,检查是否存在同id元素 for (let j = 0; j < newArray.length; j++) { if (newArray[j].id === currentItem.id) { // 找到匹配项,累加数量,标记已存在 newArray[j].qty += currentItem.qty hasExisted = true break } } // 全量遍历完都没找到匹配项,才执行新增 if (!hasExisted) { // 新增时做浅拷贝,避免后续修改影响原arr1的元素 newArray.push({...currentItem}) } } console.log(newArray) }
如果数组数据量较大,推荐用Map做查找映射的写法,时间复杂度更低,无需双层循环:
const handleAdd = () => { // 初始化Map,以id为键存储arr2的元素副本 const itemMap = new Map(arr2.map(item => [item.id, { ...item }])) for (const item of arr1) { if (!item.checked) continue if (itemMap.has(item.id)) { // 已存在则累加qty itemMap.get(item.id).qty += item.qty } else { // 不存在则存入新元素副本 itemMap.set(item.id, { ...item }) } } const newArray = Array.from(itemMap.values()) console.log(newArray) }
针对你给出的测试用例,以上两种写法运行后都会得到符合预期的结果:[{id: 1, qty: 4}, {id: 2, qty: 4}]
id为3的元素因为checked为false不会被加入,也不会出现重复元素。
内容的提问来源于stack exchange,提问作者Jack Venevankham
相关产品推荐
相关产品推荐

