JavaScript中考虑重复项的两数组差异数组生成问题
处理带重复项的数组差集需求
你遇到的这个问题确实很典型——不管是Lodash的_.difference还是原生JS的filter + includes,它们的逻辑都是只要元素在第二个数组中存在,就全部排除,根本不考虑出现的次数,所以才会把两个1都去掉,只返回[6]。
要实现你需要的「按出现次数抵消」的效果,我们得自己处理元素的计数或者逐个匹配移除,下面给你两个实用的方案:
方案一:原生JavaScript实现(无需依赖库)
核心思路是先统计第二个数组里每个元素的出现次数,然后遍历第一个数组,遇到元素时如果还有剩余的“可抵消次数”就减少计数,否则就把这个元素加入结果数组:
function getCustomDifference(arr1, arr2) { // 用Map统计arr2中各元素的出现次数 const elementCounts = new Map(); for (const num of arr2) { elementCounts.set(num, (elementCounts.get(num) || 0) + 1); } const result = []; for (const num of arr1) { const remaining = elementCounts.get(num); if (remaining && remaining > 0) { // 还有可抵消的次数,减少计数 elementCounts.set(num, remaining - 1); } else { // 没有可抵消的了,加入结果 result.push(num); } } return result; } // 测试示例 console.log(getCustomDifference([1,1,7,6], [1,7])); // 输出: [1, 6]
方案二:结合Lodash实现(如果已经在用Lodash)
如果你项目里已经引入了Lodash,可以用它的辅助函数简化逻辑,比如通过复制第二个数组的副本,逐个匹配并移除元素:
const _ = require('lodash'); function lodashCustomDifference(arr1, arr2) { // 复制arr2避免修改原数组 const tempArr = [...arr2]; return arr1.filter(num => { const matchIndex = tempArr.indexOf(num); if (matchIndex !== -1) { // 找到匹配项,从临时数组中移除一个 tempArr.splice(matchIndex, 1); return false; } return true; }); } // 测试示例 console.log(lodashCustomDifference([1,1,7,6], [1,7])); // 输出: [1, 6]
这两个方案都能满足你的需求,而且结果的顺序和原数组保持一致(如果你不需要顺序,也可以随便调整)。
内容的提问来源于stack exchange,提问作者Grambam
相关产品推荐
相关产品推荐

