使用splice()原地修改数组:元素重复次数限制函数的问题排查
问题排查与解决方案
我来帮你排查这个问题~你的代码逻辑里有两个关键问题导致结果不符合预期:
问题分析
- 遍历原数组时修改数组长度,导致遍历错位:你使用
forEach遍历原数组的同时,用splice删除元素,这会改变数组的长度和元素索引。forEach是基于数组初始长度进行遍历的,当数组变短后,后续元素的索引会前移,导致有些元素被跳过或者重复处理,最终出现像41、24这类元素超出次数保留的情况。 - 重复统计与删除,逻辑混乱:在每个元素的遍历回调中,你都重新遍历整个数组统计该元素的出现次数,然后从末尾删除超出次数的元素。这种方式不仅效率低下,还会因为多次重复统计和删除,导致逻辑冲突——比如前面的元素已经被处理过,后面再处理时又重新统计,会误删或漏删元素。
正确实现思路
我们不需要修改原数组,而是构建一个新数组,同时用一个对象记录每个元素的出现次数。遍历原数组的每个元素:
- 若当前元素的出现次数未达到
n,则将其加入结果数组,并更新计数; - 若已达到
n,则跳过该元素。
这种方式既能保证原数组的顺序,又能准确控制每个元素的出现次数,逻辑清晰且效率更高。
修正后的代码
function deleteNth(arr, n) { const countMap = {}; const result = []; for (const item of arr) { // 初始化或更新当前元素的计数 countMap[item] = (countMap[item] || 0) + 1; // 计数不超过n时,加入结果数组 if (countMap[item] <= n) { result.push(item); } } return result; } // 测试示例 const x = deleteNth([7, 26, 21, 41, 43, 2, 26, 24, 10, 26, 10, 10, 24, 35, 35, 35, 43, 26, 41, 7, 24, 24, 21, 24, 10, 35, 10, 7, 24, 7, 35, 26, 41, 35, 2, 43, 24, 2, 41, 26, 41, 7, 7, 26, 2, 10, 43, 10, 35, 41, 24, 7, 2, 2, 7, 2, 26, 24, 26, 43, 43, 21, 10, 28, 10], 2); console.log(x);
运行这段代码后,会得到你期望的结果:
[7, 26, 21, 41, 43, 2, 26, 24, 10, 10, 24, 35, 35, 43, 41, 7, 21, 2, 28]
内容的提问来源于stack exchange,提问作者Rob Majuri
相关产品推荐
相关产品推荐

