JavaScript forEach迭代时统计剩余元素出现次数的高效实现方案
二维数组迭代连续计数优化需求
需求描述
使用forEach遍历二维数组时,每轮迭代需要统计当前及之后剩余迭代中,当前子数组内各元素的连续出现次数(元素出现中断后再出现需分段统计),最终输出每轮对应的计数结果。
实际场景测试数组
const blocks = [ ['A', 'B', 'C'], ['A', 'B', 'C'], ['B', 'D', 'E'], ['A', 'B', 'D', 'E'], ['A', 'B', 'F', 'G'], ['A', 'B', 'F', 'G'], ['A', 'B', 'F', 'H', 'I'] ];
该场景下要求对元素A的两段连续出现分别统计:第一段连续出现2次,第二段连续出现4次。
优化实现方案
优化点说明
- 用
Set存储字符集合,has查询效率远高于数组includes方法 - 用
Map存储计数映射,替代原实现中的find查找,查询复杂度从O(n)降至O(1) - 统计遍历增加终止条件:待统计的字符全部消失后直接停止后续遍历,减少无效执行
- 精简冗余变量,逻辑更简洁易读
优化后代码
const blocks = [ ['A', 'B', 'C'], ['A', 'B', 'C'], ['B', 'D', 'E'], ['A', 'B', 'D', 'E'], ['A', 'B', 'F', 'G'], ['A', 'B', 'F', 'G'], ['A', 'B', 'F', 'H', 'I'] ]; const results = []; let lastBlockSet = new Set(); blocks.forEach((currBlock, index, arr) => { // 筛选当前轮次需要统计的新增字符(上一轮没有的字符) const currBlockSet = new Set(currBlock); const statChars = [...currBlockSet].filter(char => !lastBlockSet.has(char)); lastBlockSet = currBlockSet; // 初始化计数Map和待统计字符集合 const countMap = new Map(statChars.map(char => [char, 0])); let remainStatChars = new Set(statChars); // 遍历当前及之后的子数组统计连续次数 for (let i = index; i < arr.length && remainStatChars.size > 0; i++) { const loopBlockSet = new Set(arr[i]); // 过滤出当前子数组中仍存在的待统计字符 remainStatChars = new Set([...remainStatChars].filter(char => loopBlockSet.has(char))); // 计数加1 remainStatChars.forEach(char => countMap.set(char, countMap.get(char) + 1)); } // 转换为要求的输出格式 const currResult = statChars.map(char => ({ block: char, duration: countMap.get(char) })); results.push(currResult); console.log(currResult); });
内容的提问来源于stack exchange,提问作者Fran
相关产品推荐
相关产品推荐

