求助:使用for-if实现的JavaScript数组去重函数为何失效?
嵌套for循环实现数组去重的常见问题解析
先拆解你踩中的典型逻辑坑,再解释那些变量的作用:
你的代码大概率存在的问题
你说的「重复时不执行操作,不重复则推入数组」逻辑本身没问题,但嵌套循环的范围控制或重复判断逻辑很容易出错,比如:
- 内层循环起始位置错误:如果内层循环从
j=0开始,会把当前元素arr[i]和自身比较,还会重复检查已经加入uniqueArray的元素,导致同一个元素被多次推入,或者误判重复。 - 没有提前跳出内层循环:找到重复元素后还继续循环,可能会覆盖之前的判断结果,或者做无用功。
- 判断逻辑写反:比如把「找到重复就推入」当成了「找到不重复才推入」,或者没有用标记变量记录是否重复,直接在内层循环里做push操作,导致一次外层循环多次push。
举个你可能写过的反例:
function badUnique(arr) { let uniqueArray = []; for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr.length; j++) { if (arr[i] !== arr[j]) { uniqueArray.push(arr[i]); // 每遇到不同元素就push,同一个元素会被推N次 } } } return uniqueArray; }
为什么需要start或count变量?
关于start变量
这个变量一般用来控制内层循环的起始位置,比如让j = i + 1,核心是避免无效比较:
- 前面的元素已经被处理过,不需要再和当前元素比较
- 跳过当前元素自身的比较(
i===j时必然相等,完全没必要判断)
用start的正确实现示例:
function uniqueWithStart(arr) { let uniqueArray = [...arr]; for (let i = 0; i < uniqueArray.length; i++) { // 从i+1开始,只检查当前元素之后的元素 for (let j = i + 1; j < uniqueArray.length; j++) { if (uniqueArray[i] === uniqueArray[j]) { uniqueArray.splice(j, 1); // 找到重复就删除 j--; // 删除后数组长度缩短,j减1避免跳过下一个元素 } } } return uniqueArray; }
关于count变量
count本质是重复次数的计数器,用来替代「是否重复」的标记变量:
- 初始化
count=0,遍历数组时遇到和当前元素相等的就count++ - 如果最终
count===1(只出现一次),就推入去重数组;如果count>1则说明重复,跳过
示例:
function uniqueWithCount(arr) { let uniqueArray = []; for (let i = 0; i < arr.length; i++) { let count = 0; for (let j = 0; j < arr.length; j++) { if (arr[i] === arr[j]) count++; } if (count === 1) { uniqueArray.push(arr[i]); } } return uniqueArray; }
更简洁的嵌套循环写法
不用count或额外变量,只用一个标记位也能实现:
function unique(arr) { let uniqueArray = []; for (let i = 0; i < arr.length; i++) { let isDuplicate = false; // 只检查已经加入去重数组的元素 for (let j = 0; j < uniqueArray.length; j++) { if (arr[i] === uniqueArray[j]) { isDuplicate = true; break; // 找到重复立即跳出,减少循环次数 } } if (!isDuplicate) { uniqueArray.push(arr[i]); } } return uniqueArray; }
内容的提问来源于stack exchange,提问作者Codingenthusiast
相关产品推荐
相关产品推荐

