目录
- 核心基础知识点
- [6 种数组去重方法详解](#6 种数组去重方法详解)
-
- [方法 1:双重循环去重(基础实现)](#方法 1:双重循环去重(基础实现))
- [方法 2:indexOf 单循环去重](#方法 2:indexOf 单循环去重)
- [方法 3:filter + indexOf 去重](#方法 3:filter + indexOf 去重)
- [方法 4:排序 + 相邻对比去重](#方法 4:排序 + 相邻对比去重)
- [方法 5:对象字面量去重(空间换时间)](#方法 5:对象字面量去重(空间换时间))
- [方法 6:ES6 Set 去重(最优简洁版)](#方法 6:ES6 Set 去重(最优简洁版))
- 方法对比
- 总结
核心基础知识点
题目场景
- 需求:对数组 1,2,3,2,5,5,6,3 实现去重,得到无重复元素的新数组
代码规范与设计原则
- 注释规范
注释是代码的核心组成部分,提升可读性,方便团队协作、个人回顾代码。 - 单一职责
一个函数只实现一个核心功能(数组去重)。 - 封装思想
将复杂的去重逻辑封装为独立函数,复用性更强。 - 健壮性要求
必须做参数校验,避免非数组参数导致程序报错。
必备数组 API
| API | 作用 |
|---|---|
Array.isArray(arr) |
判断数据是否为数组(参数校验核心方法),是返回true,不是返回false |
arr.indexOf(item) |
查询元素在数组中第一次出现的下标,不存在返回 -1 |
arr.filter(callback) |
数组过滤,根据回调返回值保留 / 剔除元素 |
arr.sort() |
数组排序,为相邻去重做准备 |
复杂度
时间复杂度:
O(n²):双重for计数循环、filter+indexOf(效率较低)
O(nlogn):先排序再去重(中等效率)
O(n):对象 / Set 去重(最优效率,但是最消耗空间)
空间换时间:用额外对象 / Set 存储数据,提升执行速度
6 种数组去重方法详解
方法 1:双重循环去重(基础实现)
核心思路
定义结果数组,外层遍历原数组,内层遍历结果数组,通过标记判断元素是否重复,无重复则加入结果数组。
javascript
function unique(arr){
// 参数校验:非数组返回空数组
if(!Array.isArray(arr)){
console.log('type error');
return [];
}
// 初始化结果数组,放入第一个元素
let res=[arr[0]];
// 外层循环:从第二个元素开始遍历原数组
for(let i=1;i<arr.length;i++){
let flag=true; // 标记:默认当前元素不重复
// 内层循环:遍历结果数组,对比是否重复
for(let j=0;j<res.length;j++){
if(arr[i] === res[j]){
flag=false; // 发现重复,修改标记
break; // 终止内层循环
}
}
// 无重复则添加到结果数组
if(flag){
res.push(arr[i]);
}
}
return res;
}
console.log(unique([1,2,3,2,5])); // [1,2,3,5]
复杂度:O(n²)
方法 2:indexOf 单循环去重
核心思路
利用 indexOf 判断元素是否已存在于结果数组,不存在则添加,简化内层循环。
javascript
function unique(arr){
// 参数校验
if(!Array.isArray(arr)){
console.log('type error');
return [];
}
const res=[];
// 遍历原数组
for(let i=0;i<arr.length;i++){
// indexOf返回-1:元素不存在于结果数组
if(res.indexOf(arr[i])===-1){
res.push(arr[i]);
}
}
return res;
}
复杂度 :O(n²)
优点:比双重循环代码更简洁
方法 3:filter + indexOf 去重
核心思路
利用 filter 过滤数组,保留第一次出现的元素 :indexOf 返回元素首次出现的下标,与当前下标一致则保留。
javascript
function unique(arr){
// 参数校验
if(!Array.isArray(arr)){
console.log('type error');
return [];
}
// filter:返回符合条件的新数组
return arr.filter(function(item,index){
// 仅保留元素第一次出现的位置
return arr.indexOf(item)===index;
})
}
复杂度:O(n²)
优点:代码极简,一行实现核心逻辑
方法 4:排序 + 相邻对比去重
核心思路
先对数组排序 ,重复元素会变为相邻元素,遍历数组,仅保留与前一个元素不同的值。
javascript
function unique(arr){
// 参数校验
if(!Array.isArray(arr)){
console.log('type error');
return [];
}
arr.sort(); // 数组排序
let res=[arr[0]];
// 遍历数组,对比相邻元素
for(let i=1;i<arr.length;i++){
if(arr[i]!==arr[i-1]){
res.push(arr[i]);
}
}
return res;
}
复杂度:O(nlogn)
注意:排序会改变原数组元素的顺序
方法 5:对象字面量去重(空间换时间)
核心思路
对象中的key表示值,value 表示它是否出现
用对象存储已出现的元素,遍历数组时,通过对象 key 判断是否重复,仅遍历一次数组,效率极高。
javascript
function unique(arr){
// 参数校验
if(!Array.isArray(arr)){
console.log('type error');
return [];
}
let res=[];
let obj={}; // 对象:key存储数组元素,value标记是否存在
for(let i=0;i<arr.length;i++){
// 对象中无该key:表示未重复
if(!obj[arr[i]]){
res.push(arr[i]);
obj[arr[i]]=1; // 标记为已存在
}
}
return res;
}
复杂度:O(n)
优点:执行速度最快,大数据量优先使用
方法 6:ES6 Set 去重(最优简洁版)
核心思路
Set 是 ES6 提供的不重复数据容器,直接将数组转为 Set 去重,再展开为新数组。
javascript
function unique(arr){
// 参数校验
if(!Array.isArray(arr)){
console.log('type error');
return [];
}
// 数组转Set去重 → 展开运算符转回数组
return [...new Set(arr)];
}
复杂度:O(n)
优点:代码最简洁、性能最优、企业开发首选
方法对比
| 方法 | 复杂度 | 代码量 | 适用场景 |
|---|---|---|---|
| 双重循环 | O(n²) | 多 | 学习基础逻辑 |
| indexOf 循环 | O(n²) | 中等 | 简单业务场景 |
| filter+indexOf | O(n²) | 极简 | 代码简洁优先 |
| 排序 + 相邻 | O(nlogn) | 中等 | 允许改变元素顺序 |
| 对象去重 | O(n) | 中等 | 大数据量、高性能要求 |
| ES6 Set | O(n) | 极简 | 现代浏览器 / 项目首选 |
总结
数组去重是前端必备基础能力,核心是判断元素是否重复;
所有方案都必须包含参数校验,保证代码健壮性;
复杂度从低到高:O(n) < O(nlogn) < O(n²);
最优方案:ES6 Set 去重,兼顾简洁性与性能;
核心思想:循环对比、API 复用、空间换时间。