js数组去重是前端面试中经常被问的题目,考察了面试者对js的掌握,解决问题的思路,以及是否具有专研精神。曾经一位前端界大神告诉我,解决问题的方式有很多种,解决问题时多问问自己还有没有其他的方法,探求最优解决方案才能学到更多。
如果,这篇文章有幸被您阅读,文中出现的错误,或者您有其他的解决方案请在评论区告诉我,谢谢。
方案一
/**
* 1.构建一个新数组
* 2.遍历目标数组,依次取出每一个元素
* 3.将取出的元素与新数组里面的所有元素进行比较,
* 如果没有出现 -> 该元素添加到新数组中,
* 如果出现 -> 处理下一个目标数组元素
* */
function distinct(arr) {
console.time(); //跟踪方法的占用时长
var result = []; // 构建结果数组result
for (var i = 0, len = arr.length; i < len; i++) {
for (var j = 0, rlen = result.length; j <= rlen; j++) {
if (arr[i] === result[j]) {
break;
}
if (j == result.length) {
result.push(arr[i]);
}
}
}
console.timeEnd();
return result;
}
方案优点:
- 结果数组与目标数组的顺序保持一致
- 思路简单,兼容性好
方案缺点:
- 速度慢
方案二
/**
*1.目标数组排序
*2.遍历目标数组,检测数组中的第i 个元素与结果数组中最后一个元素是否相同,如果不同,则将该元素添加到结果数组中
* */
function distinct(arr) {
console.time();
var result = [];
arr = arr.sort();
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i] !== result[result.length - 1]) {
result.push(arr[i])
}
}
console.timeEnd();
return result;
}
方案优点:
- 方案中先排序,后遍历,速度比方法一快
方案缺点:
- 方案中使用了数组排序sort,打乱了原有顺序
Tips:数组排序
js中提供了数组排序方法sort,使用时需要注意以下几点:
- 调用sort方法时改变了目标数组本身,非生成新数组
- sort方法默认按照字符顺序进行排序,不过提供了回调方法,可以自定义排序规则
现有一数组arr:1,11,23,56,3,4,5,7,562,67
按字符排序
arr.sort() // 1, 11, 23, 3, 4, 5, 56, 562, 67, 7
按数字大小:正序
arr.sort((a,b) => a-b) // 1, 3, 4, 5, 7, 11, 23, 56, 67, 562
按数字大小:倒序
arr.sort((a,b) => b-a) // 562, 67, 56, 23, 11, 7, 5, 4, 3, 1
方案三
/**
* 利用ES6的 数据结构SET的无重复值特性
* Array.from 将类数组转换成数组
* */
function distinct3(arr) {
console.time();
var result = Array.from(new Set(arr));
console.timeEnd();
return result;
}
方案优点:
- 代码简洁,执行速度快
方案缺点:
- ES6语法,使用时需要考虑兼容性问题
方案四
/**
* 利用对象属性无重复的特点
* 遍历目标数组,将值设置为对象属性
* Object.keys 将对象的所有属性提取成一个数组
* */
function distinct(arr) {
console.time();
var result = {};
for (var i = 0, len = arr.length; i < len; i++) {
result[arr[i]] = '';
}
result = Object.keys(result);
console.timeEnd();
return result;
}
方案优点:
- 速度快
方案缺点:
- 1 与 '1' 无法区分
- 结果数组中的值全部为字符串
- 占内存,相当于利用空间换时间
方案五
/**
* Array.filter 数组过滤函数,只保留符合条件的值
* indexOf 查找元素第一次出现的位置,所有第1次之后查找的元素位置都不符合条件
* */
function distinct(arr) {
console.time();
var result = arr.filter(function (elem, index, self) {
return self.indexOf(elem) === index;
});
console.timeEnd();
return result;
}
测试
随机生成包含10000个数字的数组
function random() {
var a = [];
for (var i = 0; i < 10000; i++) {
a.push(Math.ceil(i * Math.random()))
}
return a;
}
现在执行上述去重方法,取5次测试结果的平均值:
方法一 | 方法二 | 方法三 | 方法四 | 方法五 | |
---|---|---|---|---|---|
第一次 | 91.281 | 7.921 | 4.36 | 2.038 | 68.856 |
第二次 | 104.492 | 7.519 | 2.267 | 1.328 | 70.555 |
第三次 | 105.937 | 8.874 | 1.804 | 1.680 | 73.020 |
第四次 | 100.524 | 5.287 | 2.602 | 1.573 | 85.129 |
第五次 | 106.612 | 8.990 | 1.615 | 1.963 | 79.115 |
平均 | 101.769 | 7.718 | 2.529 | 1.716 | 75.335 |
从执行速度来看,方法四 < 方法三 < 方法二 < 方法五 < 方法一
方法四最快,方法一最慢。但是五种方法各有优缺点,使用时要根据实际情况选择适合的方案。
写在最后
本篇文章旨在学习分享和记录,并不是说数组去重只有这五种方法,如果文章中出现了错误,或者您有更好的解决方案,麻烦您在评论区告知我,谢谢。