如何在JavaScript中按等量从列表中移除元素?
问题描述
给定以下两个数组:
let a = [1, 1, 1, 2]; let b = [{id: 1}, {id: 1}, {id: 4}, {id: 1}, {id: 2}, {id: 3}, {id: 1}];
需求规则:
- 统计数组
a中每个数字的出现次数(如数字1出现3次,数字2出现1次) - 统计数组
b中每个id的出现次数(如id=1出现4次,id=2出现1次等) - 对每个id值,保留
b中该id的元素数量 =b中该id总数量 -a中对应数字的出现次数(结果大于0则保留,否则全部移除) - 最终预期结果:
[{id: 1}, {id: 3}, {id: 4}]
解决方案
实现思路
- 先统计数组
a中各数字的出现频次,用对象存储映射关系 - 统计数组
b中各id的出现频次,同时保存每个id对应的所有元素 - 根据两个频次统计结果,计算每个
id需要保留的元素数量,筛选并收集到结果数组中
代码实现
// 统计数组a中数字的出现次数 const countA = a.reduce((acc, num) => { acc[num] = (acc[num] || 0) + 1; return acc; }, {}); // 统计数组b中id的出现次数,并保存对应元素列表 const countB = b.reduce((acc, item) => { const id = item.id; if (!acc[id]) { acc[id] = { count: 0, items: [] }; } acc[id].count++; acc[id].items.push(item); return acc; }, {}); // 生成最终结果 const result = []; for (const id in countB) { const keepCount = countB[id].count - (countA[id] || 0); if (keepCount > 0) { // 这里取最后keepCount个元素,若需要保留前面的元素可改为slice(0, keepCount) result.push(...countB[id].items.slice(-keepCount)); } } console.log(result); // 输出 [{id: 1}, {id: 3}, {id: 4}]
代码说明
countA最终为{1: 3, 2: 1},记录了a中每个数字的出现次数countB会记录每个id的总数量和对应的元素数组,比如id=1对应的结构是{count:4, items: [{id:1}, {id:1}, {id:1}, {id:1}]}- 计算
keepCount时,若a中没有对应数字(比如id=3、4),则默认减去0,保留全部元素 - 截取元素时用
slice(-keepCount)取最后N个,若需求是保留前面的元素,替换为slice(0, keepCount)即可
内容的提问来源于stack exchange,提问作者rafaelcb21
相关产品推荐
相关产品推荐

