JavaScript 数组去重的两种常用思路与实现
在 JavaScript 开发中,处理数据时经常需要去除重复值。本文将详细解析两种经典的手写数组去重方法,分别介绍其核心思路、完整代码实现及使用注意事项。
方法一:基于 indexOf 的常规去重
这种方法的核心在于“遍历 + 查找”。它不改变原数组的顺序,而是逐个提取元素并判断其是否已经出现在结果数组中。
第1步:构建存储结果的空数组
首先创建一个空数组 res,用于存放去重后的唯一元素。
第2步:遍历原数组并使用 indexOf 查重
使用 for 循环从头到尾读取原数组的每一个元素。利用 Array.prototype.indexOf() 方法在结果数组 res 中查找当前元素:
- 如果返回值为
-1,说明该元素在结果数组中不存在,即为首次出现,将其添加到res中。 - 如果返回值大于等于
0,说明该元素已存在,跳过不处理。
第3步:优化入口与返回结果
在标准实现基础上,可以将初始判断稍微优化:直接将原数组的第一个元素放入结果数组,然后从第二个元素开始循环。这在逻辑上避免了第一次循环时的空数组查找,但整体时间复杂度依然为 O(n²),主要开销在于 indexOf 的内部搜索。
以下是完整的函数封装代码:
// 将去重功能挂载到 Array 原型上
Array.prototype.unique1 = function(){
var res = [];
// 为了简单起见,这里演示最基础的遍历方式
// 若要从第二个元素开始,可初始化为 this[0]
for(var i = 0; i < this.length; i++){
// 如果在新数组中找不到当前元素
if(res.indexOf(this[i]) == -1){
res.push(this[i]);
}
}
return res;
}
// 测试用例
var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0];
console.log(arr.unique1());
// 预期输出: [1, "a", "b", "d", "e", 0]
方法二:基于排序的比较去重
这种方法利用了排序后重复元素必然相邻的特性,通过一次线性扫描即可完成去重。虽然执行速度通常在大数据量下优于第一种方法(O(n log n)),但它会改变原数组的元素顺序,且会对字符串和数字类型产生混合排序的影响。
第1步:原地排序
调用 this.sort() 对原数组进行升序排序。注意:sort() 默认排序是将元素转换为字符串进行比较,因此在包含混合类型(如数字和字符串)的数组中,排序结果可能不符合数学直觉。
第2步:初始化结果数组
因为排序后首尾元素大概率不同(除非全部相同),先将排序后的第一个元素 this[0] 存入结果数组 res 中。
第3步:相邻元素比对
从索引 1 开始遍历排序后的数组。每次将当前元素 this[i] 与结果数组的最后一个元素 res[res.length - 1] 进行比较:
- 如果两者不相等(
!==),说明遇到了新的唯一值,追加到结果数组。 - 如果两者相等,说明是重复值,直接跳过。
对应的代码实现如下:
Array.prototype.unique2 = function(){
// 1. 先排序
this.sort();
// 2. 初始化结果数组,放入第一个元素
var res = [this[0]];
// 3. 从第二个元素开始比较
for(var i = 1; i < this.length; i++){
// 如果当前元素不等于结果数组的最后一个元素
if(this[i] !== res[res.length - 1]){
res.push(this[i]);
}
}
return res;
}
// 测试用例
var arr = [1, 'a', 'a', 'b', 'd', 'e', 'e', 1, 0];
console.log(arr.unique2());
// 注意:由于 sort() 的特性,混合类型排序结果可能出乎意料
总结与建议
以上介绍了两种传统的 JavaScript 数组去重思路。在实际现代开发中,通常会优先使用更简洁的 Set 对象或 filter + findIndex 等方式。但如果需要对底层原理有清晰认知,或者在受限环境中运行,掌握这两种手动实现的逻辑依然具有重要意义。
以上就是 JavaScript 数组去重两种常用方法的详细内容,更多关于 JS 基础算法的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









