其實網上已經有很多js陣列的去重方法,但是我看了很多篇并自己通過代碼驗證,發現都有一些缺陷,于是在研究多篇代碼之后,自己總結了9種方法,如果有哪里不對請及時糾正我哈~
轉載請表明出處
測驗代碼
let arr1 = [3, 1, [1], 1, [1], true, true, {}, '1', NaN, undefined, NaN, undefined, {}, null, null];
let arr2 = [];
for (let i = 0; i < 100000; i++) {
arr2.push(0 + Math.floor((100000 - 0 + 1) * Math.random()));
}
// 封裝在Array的原型物件會更好,this就是指向呼叫該方法的陣列
Array.prototype.unique = function () {
//...
}
console.log(arr1.unique()); // 測驗去重效果
console.time('test');
console.log(arr2.unique()); // 測驗去重時間
console.timeEnd('test');
備注:
arr1- 包含了兩個相同的陣列[1]、并且陣列[1]和1的順序打亂(這是為了突出sort的弊端)
- 有兩個NaN、兩個undefined、兩個null等等,把平時會用到的資料型別都寫上來了
- 有兩個相同的空物件{}
arr2- 放入10萬個隨機純數字,大的資料量才能看出時間的差別
- 對于純number的陣列,以下所有方法(包括網上的各種方法)都是可行的
- 正確去重的
arr1:[3, 1, [1], true, {}, '1', NaN, undefined, null],length = 9,
一、不能正確去重NaN和Object的方法
1. 兩種for回圈 + splice(耗時最長)
Array.prototype.unique = function () {
for (let i = 0; i < this.length; i++) {
for (let j = i + 1; j < this.length; j++) {
if (this[i] === this[j]) {
this.splice(j, 1);
j--;
}
}
}
return this;
}
- test: 21208.31396484375 ms(花了21s....)
不能去重NaN和復雜陣列型別(比如 Object 和 Array )
2. forEach + indexOf
Array.prototype.unique = function () {
let newArr = [];
this.forEach((item) => {
if (newArr.indexOf(item) === -1) {
newArr.push(item);
}
})
return newArr;
}
結果同上,建議大家自己運行一下(就是懶得截圖
- test: 4104.52294921875 ms
不能去除重復的NaN和復雜資料型別
- 原因:indexOf 認為 NaN 不等于 NaN
3. filter + indexOf
Array.prototype.unique = function () {
return this.filter((item, index) => {
// 利用indexOf檢測元素在陣列中第一次出現的位置是否和元素現在的位置相等,如果不等則說明該元素是重復元素
return this.indexOf(item) === index;
})
}
- test: 5682.358154296875 ms
不能去掉重復的復雜資料型別,同時還會去掉所有的NaN
- 原因:indexOf 認為 NaN 不等于 NaN ,所以也就不認為他們是重復元素,
4. for + sort(sort有問題)
Array.prototype.unique = function () {
let newArr = [];
this.sort();
for (let i = 0; i < this.length; i++) {
if (this[i] !== this[i + 1]) {
newArr.push(this[i]);
}
}
return newArr;
}
- test: 61.96484375 ms
帶 sort 方法的只對純number或者純string型別有效,它無法區分1和'1',因為它是在將元素轉換為字串,然后比較它們的UTF-16代碼單元值序列時構建的,
這時候如果有一段這樣的排序[1, '1', 1],再用前后比較的方法去重就會出現問題
在這里他還會把undefined也全都去掉,原因是
sort()方法排序后,undefined排在最后,而最后一個undefined要和this[length]進行比較,而這個值并不存在,而也是undefined,就會認為他們是同一個值,
同樣它不能去重NaN和復雜資料型別,但是耗時是在方法里面是最少之一了(都之一了用別的不香嗎)
5. sort + reduce(sort有問題)
Array.prototype.unique = function () {
return this.sort().reduce((init, cur) => {
if (init.length === 0 || init[init.length - 1] !== cur) {
init.push(cur);
}
return init;
}, []);
}
- test: 66.679931640625 ms
同樣他也是用sort排序再前后比較,也是傻逼玩意
比上面那個方法好一點點,還能正確去重undefined(我覺得前后比較這種方法著實不靠譜)
同樣也不能去重NaN和復雜陣列型別,耗時也是在方法里面是最少之一,
二、能正確去重NaN,不能去重復雜資料型別
1. forEach + includes
Array.prototype.unique = function () {
let newArr = [];
this.forEach((item) => {
if (!newArr.includes(item)) {
newArr.push(item);
}
})
return newArr;
}
- 4181.393798828125 ms
可以去掉重復的NaN,但是不能去掉重復的復雜資料型別
- includes 認為 NaN === NaN 為 true
2. forEach + map
Array.prototype.unique = function () {
let map = new Map();
let newArr = new Array();
this.forEach((item) => {
if (!map.has(item)) {
map.set(item, 1);
newArr.push(item);
}
});
return newArr;
}
同上,不截圖了,自行運行一哈~
- test: 27.030029296875 ms
可以去NaN,不能去重復雜陣列型別,運行速度快,耗時最少的方法之一
3. Set
Array.prototype.unique = function () {
return [...new Set(this)];
}
同上,不截圖了
- test: 31.197021484375 ms
可以去掉重復的NaN,但是不能去掉重復的復雜資料型別,運行速度快,耗時最少的方法之一,代碼最短!
三、可以去掉NaN和復雜資料型別的!
1. filter + hasOwnProperty + JSON.stringify
Array.prototype.unique = function () {
let obj = {};
return this.filter(function (item, index, arr) {
return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true);
});
}
- test: 126.3359375 ms
可以去掉重復的NaN和重復的復雜資料型別
在object中,key如果是number型別,它會自動轉換成string型別,所以{1:1}和{"1":1}是相等的,這不是這個方法的缺陷,這是Oject的缺陷
而{1: 1}和{1: "1"}這種value值不同的可以正確區分開,
- 該方法的核心:以
typeof item元素型別+item的字串作為key - 有些文章寫的方法是直接使用item,讓obj自行隱式轉換成字串
- 考慮到obj的字串都為'[object Object]',這里使用JSON.stringify(item),就可以保存不同的obj字串
后記
其實上面的方法不外乎三種:
- 利用for、forEach、filter遍歷,再利用indexOf、includes等方法判斷是否重復;
- 利用Set資料結構的特性;
- 利用obj或者map的key不能重復的特性,
實際開發應該更多的是純數字的去重(吧?),而且也用不上這么多方法,能記住兩三種根據實際情況的需求來選擇就行了(吧?)
但作為一個正在找作業的應屆生,不得不總結多幾種方法,這樣面試官問起來的時候才不至于口啞無言嘿嘿嘿
(完)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/209589.html
標籤:其他
下一篇:Vue中用的比較多的幾個API
