将含重复元素的数组拆分为唯一元素数组与重复元素组数组
更优的数组拆分方案:一次遍历完成分类
嘿,我来分享一个更高效的解决方案——只用单次遍历就能完成你需要的数组拆分,相比你之前的reduce方案,它省去了中间分组数组的创建,也不需要后续的过滤和映射操作,性能和可读性都更出色:
const array = [1,2,2,3,4,4,4,5,6,7,7,7,8,9]; const uniqArray = []; const dupArray = []; // 处理空数组的边界情况 if (array.length === 0) { console.log(uniqArray, dupArray); return; } // 初始化当前分组,从第一个元素开始 let currentGroup = [array[0]]; for (let i = 1; i < array.length; i++) { const currentItem = array[i]; // 如果当前元素和分组首元素相同,加入当前分组 if (currentItem === currentGroup[0]) { currentGroup.push(currentItem); } else { // 当前分组结束,判断是唯一元素还是重复组 if (currentGroup.length === 1) { uniqArray.push(currentGroup[0]); } else { dupArray.push(currentGroup); } // 开启新的分组 currentGroup = [currentItem]; } } // 别忘了处理最后一个分组! if (currentGroup.length === 1) { uniqArray.push(currentGroup[0]); } else { dupArray.push(currentGroup); } console.log(uniqArray); // 输出: [1,3,5,6,8,9] console.log(dupArray); // 输出: [[2,2],[4,4,4],[7,7,7]]
为什么这个方案更好?
- 时间效率拉满:整个过程只遍历数组一次,时间复杂度是O(n),是理论上的最优复杂度。你之前的reduce方案虽然也是线性时间,但后续的两次
filter+map会额外增加少量开销。 - 内存更节省:没有创建像
arrayOfArrays这样的中间分组数组,只用了一个临时变量currentGroup来跟踪当前组,内存占用更低。 - 逻辑清晰易懂:每一步都直接处理分组和分类,没有绕弯,后续维护起来也很方便。
顺便聊聊你之前的尝试
你第一次用forEach的方案,问题出在判断条件item !== array[index + 1]上——这个条件会把重复元素的最后一个前的元素都放进临时数组,但最后一个重复元素会被误判为唯一元素塞进uniqArray,导致结果出错。而这个一次遍历的方案通过跟踪完整分组,完美避免了这个问题。
你的reduce方案其实思路是对的,但多了中间分组的步骤,显得有点冗余,上面的方案把分组和分类合并到了一次遍历里,更加紧凑。
内容的提问来源于stack exchange,提问作者Rami
相关产品推荐
相关产品推荐

