如何用纯JavaScript实现两个对象数组按ID数量相减?
按ID数量实现数组相减的纯JS方案
这个问题光用filter确实搞不定,因为它会直接移除所有匹配ID的对象,没法控制移除的数量。不过我们可以结合reduce先统计要减去的数组里每个ID的出现次数,再用filter逐个处理原数组,刚好能实现“按ID数量相减”的需求。
实现思路
- 统计待减ID的数量:先用
reduce遍历要减去的数组,生成一个记录每个ID出现次数的对象。 - 按数量过滤原数组:遍历原数组时,检查当前元素的ID在统计对象中的剩余次数——如果还有剩余次数,就减少计数并跳过该元素;否则保留它。
完整代码实现
function subtractArrays(arr1, arr2) { // 统计arr2中每个ID的出现次数 const idCounts = arr2.reduce((counts, item) => { counts[item.id] = (counts[item.id] || 0) + 1; return counts; }, {}); // 遍历arr1,根据计数过滤元素 return arr1.filter(item => { if (idCounts[item.id] && idCounts[item.id] > 0) { idCounts[item.id]--; // 减少对应ID的剩余可减次数 return false; // 移除当前元素 } return true; // 保留当前元素 }); }
示例测试
假设你有以下两个数组:
const originalArray = [ {id: 1, name: "a"}, {id: 1, name: "a"}, {id: 2, name: "b"}, {id: 3, name: "c"}, {id: 2, name: "b"} ]; const subtractArray = [ {id: 1, name: "a"}, {id: 2, name: "b"} ];
调用函数后:
const result = subtractArrays(originalArray, subtractArray); console.log(result);
输出结果会是:
[ {id: 1, name: "a"}, {id: 3, name: "c"}, {id: 2, name: "b"} ]
可以看到,id=1的对象原本有2个,减去1个后剩1个;id=2原本有2个,减去1个后剩1个;id=3没有匹配项,完全保留。
代码说明
reduce生成的idCounts对象会记录每个需要减去的ID的次数,比如上面的示例中,idCounts初始是{1:1, 2:1}。- 在
filter遍历原数组时,每遇到一个匹配的ID,就把idCounts里对应的计数减1,直到计数为0,之后同ID的元素就会被保留下来。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

