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 === result[j]) {
break;
}
if (j == result.length) {
result.push(arr);
}
}
}
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 !== result[result.length - 1]) {
result.push(arr)
}
}
console.timeEnd();
return result;
}
方案优点:
方案缺点:
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;
}
方案优点:
方案缺点:
方案四
/**
* 利用对象属性无重复的特点
* 遍历目标数组,将值设置为对象属性
* Object.keys 将对象的所有属性提取成一个数组
* */
function distinct(arr) {
console.time();
var result = {};
for (var i = 0, len = arr.length; i < len; i++) {
result[arr] = '';
}
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 |
从执行速度来看,方法四 < 方法三 < 方法二 < 方法五 < 方法一 方法四最快,方法一最慢。但是五种方法各有优缺点,使用时要根据实际情况选择适合的方案。
写在最后
本篇文章旨在学习分享和记录,并不是说数组去重只有这五种方法,如果文章中出现了错误,或者您有更好的解决方案,麻烦您在评论区告知我,谢谢。 |