JS中如何检查元素是否存在于所有传入子数组?求代码评价与优化
原代码评价
- 核心思路正确:通过统计元素在不同子数组中的出现次数(单个子数组内去重)来求交集,但实现逻辑过于复杂绕弯
- 实现缺陷:
- 合并所有子数组为
compiledArr后,靠endBound判断子数组边界的方式容易出错,比如子数组为空时会导致边界计算混乱 - 用
[计数, 标记]数组存储状态的设计不够直观,turnTrue遍历所有键重置标记的操作在元素量大时会影响性能 - 边界情况处理缺失:未考虑传入空数组、子数组为空的场景,这类情况交集应为空数组
- 变量命名不够清晰:比如
bigArr、compiledArr语义模糊,代码中存在currentElement和compiledArr[i]混用的情况,可读性差
- 合并所有子数组为
简洁实现方案
方案一:基于频率统计
利用Set快速给单个子数组去重,再统计每个元素在去重后的子数组中出现的次数,最终筛选出出现次数等于子数组总数的元素:
function intersection(...arrays) { if (arrays.length === 0) return []; // 将每个子数组转成Set去重 const uniqueSubArrays = arrays.map(subArr => new Set(subArr)); const freqMap = {}; // 统计每个元素在不同去重子数组中的出现次数 uniqueSubArrays.forEach(subSet => { subSet.forEach(item => { freqMap[item] = (freqMap[item] || 0) + 1; }); }); // 筛选出在所有子数组中都出现的元素,自动适配数字/非数字类型 return Object.entries(freqMap) .filter(([_, count]) => count === arrays.length) .map(([item]) => isNaN(Number(item)) ? item : Number(item)); } // 测试用例 console.log(intersection([1,2,1], [4,1,3,1,4], [3, 1, 2,6])); // 输出 [1]
方案二:基于候选集逐步筛选
以第一个子数组的去重元素作为初始候选集,依次和后续子数组的去重集合取交集,逐步缩小候选范围,效率更高(可提前终止):
function intersection(...arrays) { if (arrays.length === 0) return []; // 初始候选集:第一个子数组的去重元素 let candidates = new Set(arrays[0]); for (let i = 1; i < arrays.length; i++) { const currentSet = new Set(arrays[i]); // 移除候选集中不在当前子数组的元素 candidates.forEach(item => { if (!currentSet.has(item)) candidates.delete(item); }); // 候选集为空时提前结束循环 if (candidates.size === 0) break; } return Array.from(candidates); } // 测试用例 console.log(intersection([1,2,1], [4,1,3,1,4], [3, 1, 2,6])); // 输出 [1]
内容的提问来源于stack exchange,提问作者WilliamG
相关产品推荐
相关产品推荐

