JavaScript數組去重方法及性能分析

遇到一個需求,需要去除數組裏面相同的項。本身這個需求不復雜,但是考慮到性能問題,則需要好好琢磨一下了。下面我對一些比較常見的方法進行了測試。

先生成一個長度爲10萬的重複數組:

var arr = [];
for(var i=0; i<100000; i++){
	arr.push( Math.floor(Math.random()*100000));
}
var tt = Date.now();
//在此處添加 去除重複數據的測試代碼
//abc.......

console.log(Date.now() - tt);

一、利用ES6 Set去重,一行代碼搞定,性能極高(ES6中最常用)

//耗時:7ms
Array.from(new Set(arr));

//還可以寫成這樣,也是耗時:7ms
[...new Set(arr)]

二、利用for嵌套for,然後splice去重(ES5中最常用),性能非常慢

//耗時:8367ms
for(var i=0; i<arr.length-1; i++){
	for(var j=i+1; j<arr.length; j++){
		if(arr[i]==arr[j]){//第一個等同於第二個,splice方法刪除第二個
			arr.splice(j,1);
			j--;
		}
	}
}

三、利用 indexOf 或 includes 去重,性能一般般

//耗時:2860ms
var array = [];
for(var i =0; i < arr.length; i++) {
	if(array.indexOf(arr[i]) === -1) {
		array.push(arr[i])
	}
}
arr = array;

//用includes,耗時:2842ms,區別不大
var array = [];
for(var i =0; i < arr.length; i++) {
	if(!array.includes( arr[i])) {
		array.push(arr[i])
	}
}
arr = array;

四、利用sort() 先排序,後去掉所有重複的數據

//耗時:43ms
arr = arr.sort()
var arrry= [arr[0]]; //開啓一個新數組,性能很高,但還是比第一種方法低
for(var i =1; i < arr.length; i++) {
	if(arr[i] !== arr[i-1]) {
		arrry.push(arr[i]);
	}
}
arr = array;

//查找相同的對象,修改源數組,耗時:2110ms,相比上面push的方式慢很多
arr = arr.sort()
for(var i =1; i < arr.length; i++) {
	if(arr[i] === arr[i-1]) {
		arr.splie(i, 1);
		i--;
	}
}

五、利用filter + Object屬性判斷,性能還可以

//耗時:80ms
var obj = {}, key;
arr = arr.filter(function(item, index, arr){
	key = typeof item + item;
	return obj.hasOwnProperty(key) ? false: (obj[key] = true);
})

六、利用filter + indexOf 判斷,性能較差

//3693ms
arr = arr.filter(function(item, index, arr){
	//當前元素,在原始數組中的第一個索引==當前索引值,否則返回當前元素
	return arr.indexOf(item,0) === index;
});

綜上所述,最優解是使用第一種方案: es6的新特性

Array.from(new Set(arr));[...new Set(arr)]

在不支持es6的環境下,使用第四方案:利用sort() 先排序,後去掉所有重複的數據

arr = arr.sort()
var arrry= [arr[0]]; 
for(var i =1; i < arr.length; i++) {
	if(arr[i] !== arr[i-1]) {
		arrry.push(arr[i]);
	}
}
arr = array;

如還有其他更高效的算法請大家留言告知,謝謝~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章