笔者在做项目的时候遇到一个问题,需要对数组进行去重操作。在网上找到了各种解决的方法,整理了一下,简单分析一下每种的优缺点。
  

第一种方法遍历循环

  第一种方法也是最一般、最常用的办法,使用数组的indexOf()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];
function unique1(arr){
let result = [arr[0]];
for (let i = 1; i < arr.length; i++) {
let item = arr[i];
if(result.indexOf(item) == -1){
result.push(item);
}
}
return result;
}
console.log(unique1(arr));

  但是indexOf方法内部实现也是去遍历数组知道找到目标为止,如果待去重的数组很长且重复的元素少,则会耗费了大量的时间。

第二种方法存放Hash对象

  第二种方法是将数组所有的元素转变成对象的键名,利用对象键名的不可重复的特性来去重。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];
function unique2(arr){
let result = [];
let obj ={};
for(let i =0;i<arr.length;i++){
let item = arr[i];
if(!obj[item]){
result.push(item);
obj[item] = 1;
}
}
return result;
}
console.log(unique2(arr))

  在时间消耗上来看,这种方法比第一种方法要快很多,因为从对象中取属性值消耗的时间几乎可以不计,但是存在以下两个问题:

  1. 由于需要存放Hash对象,因此在内存占用上比第一种方法会多占用更多的内存空间,就是所谓的空间换时间。
  2. 从上面的排序结果我们会发现一个问题,’12’不在结果中。因为在键名中,String类型的’12’和Number类型的12对于Hash对象来说都是一样的。

第三种方法排序比较

  第三种方法利用数组原生的sort()方法,将数组先进行排序,排序后比较相邻两个元素的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];
function unique3(arr) {
let result = [arr[0]];
arr = arr.sort();
for (let i = 1; i < arr.length; i++) {
let item = arr[i];
if (item !== result[result.length - 1]) {
result.push(item)
}
}
return result;
}
console.log(unique3(arr))

  这种方法比indexOf()消耗的时间要短,比存放Hash对象占用的内存要小,算是一种折中两者的方法。但是也存在一个问题,就是去重后的数组的顺序发生了改变。

第四种方法利用Set类型

  如果你开发环境支持ES6,这个方法是最简洁的。

1
2
3
4
5
6
7
let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];
function unique4(arr){
return Array.from(new Set(arr));
}
console.log(unique4(arr));

本文地址: http://xieyufei.com/2017/09/02/JS-Array-Remove-Duplicate.html