这么全的数组去重,你怕不怕?
以 var arr = [1,2,3,1]; 作為測試用例
?
方法一:雙循環 ? (時間復雜度比較高,性能一般。)
A、(1)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var isRepeat;5 6 for(var i=0; i<len; i++) { //第一次循環7 isRepeat = false;8 for(var j=i+1; j<len; j++) { //第二次循環9 if(arr[i] === arr[j]){ 10 isRepeat = true; 11 break; 12 } 13 } 14 if(!isRepeat){ 15 newArr.push(arr[i]); 16 } 17 } 18 return newArr; 19 }?輸出 newArr 結果:
?
B、(2)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 for(var i=0; i<len; i++){ // 第一次循環5 for(var j=i+1; j<len; j++){ // 第二次循環6 if(arr[i] === arr[j]){7 j = ++i;8 }9 } 10 newArr.push(arr[i]); 11 } 12 return newArr; 13 }輸出 newArr 結果:
tip: ?j = ++ i; 等價于 j = j+1; i = i+1; ?
整體思路就是 如果是重復元素,則跳過重復元素,不對其進行 push 操作。
?
方法二:Array.prototype.indexOf()?
A、(3)
1 function unique(arr) { 2 return arr.filter(function(item, index){ //item 表示數組中的每個元素,index 是每個元素的出現位置。 3 return arr.indexOf(item) === index; // indexOf 返回第一個索引值 4 }); 5 }輸出 新 arr 結果:
tip:var new_arrary = arr.filter(callback[,?thisArg]); ?其中?callback?用來測試數組的每個元素的函數。調用時使用參數 element, index, array。
返回true表示保留該元素(通過測試),false則不保留。thisArg可選,執行?callback?時的用于?this?的值。
整體思路就是索引不是第一個索引,說明是重復值。
?
B、(4)
1 function unique(arr) { 2 var newArr = []; 3 arr.forEach(function(item){ //一次循環,item 即為數組中的每一項 4 if(newArr.indexOf(item) === -1){ 5 newArr.push(item); 6 } 7 }); 8 return newArr; 9 }輸出 newArr 結果:
?
方法三:Array.prototype.sort()?
A、(5)
1 function unique(arr) {2 var newArr = []; 3 arr.sort();4 for(var i = 0; i < arr.length; i++){5 if( arr[i] !== arr[i+1]){6 newArr.push(arr[i]);7 }8 }9 return newArr; 10 }輸出 newArr 結果:
tip: 整體思路就是 先進行排序,然后比較相鄰元素。
?
B、(6)
1 function unique(arr) {2 var newArr = []; 3 arr.sort();4 var newArr = [arr[0]];5 for(var i = 1; i < arr.length; i++){6 if(arr[i] !== newArr[newArr.length - 1]){7 newArr.push(arr[i]);8 }9 } 10 return newArr; 11 }輸出 newArr 結果:
tip:整體思路就是 先進行排序,將原數組中的第一個元素復制給結果數組,然后檢查原數組中的第 i 個元素 與 結果數組中的最后一個元素是否相同。
?
方法四:使用對象key來去重?(7)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = {};5 for(var i=0; i<len; i++){6 if(!tmp[arr[i]]){7 tmp[arr[i]] = 1;8 newArr.push(arr[i]);9 } 10 } 11 return newArr; 12 }輸出 newArr 結果:
tip:整體思路就是?利用了對象(tmp)的 key 不可以重復的特性來進行去重。 但是會出現如下問題需要注意:
1、無法區分隱式類型轉換成字符串后一樣的值,比如 1 和 '1' 。
2、無法處理復雜數據類型,比如對象(因為對象作為key會變成[object Object])。
3、特殊數據,比如 '__proto__' 會掛掉,因為 tmp 對象的 __proto__ 屬性無法被重寫。
?
? ? 針對以上問題,解決辦法有:
解決問題一、三:可以為對象的 key 增加一個類型,或者將類型放到對象的value中來解決:(8)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = {};5 var tmpKey;6 for(var i=0; i<len; i++){7 tmpKey = typeof arr[i] + arr[i];8 9 console.log(tmpKey); 10 11 if(!tmp[tmpKey]){ 12 tmp[tmpKey] = 1; 13 newArr.push(arr[i]); 14 } 15 } 16 return newArr; 17 }?輸出 newArr 結果:
tip: 代碼中第 9 行 console 出來的東西 如圖:
?
解決問題二:可以將對象序列化之后作為key來使用。這里為簡單起見,使用JSON.stringify()進行序列化。(9)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = {};5 var tmpKey;6 for(var i=0; i<len; i++){7 tmpKey = typeof arr[i] + JSON.stringify(arr[i]);8 9 console.log(tmpKey) 10 11 if(!tmp[tmpKey]){ 12 tmp[tmpKey] = 1; 13 newArr.push(arr[i]); 14 } 15 } 16 return newArr; 17 }輸出 newArr 結果:
tip: 代碼中第 9 行 console 出來的東西 如圖:
看起來和上面一種方法 console 的沒有區別,但是將 測試用例 換成一個 對象 ?var arr ?= [{xiaoming:23,xiaoqing:45},{xiaoming:24,xiaoqing:45}]; 時,可以看到 console 結果如下:
?
?
以上都是一些比較普遍的解決辦法,下面補充一下 es6 中的方法以及對于 null,NaN,undefined,{} 等類型的去重。
一、es6:
方法一:?Map?(10)
1 function unique(arr) {2 var newArr = [];3 var len = arr.length;4 var tmp = new Map();5 for(var i=0; i<len; i++){6 if(!tmp.get(arr[i])){7 tmp.set(arr[i], 1);8 newArr.push(arr[i]);9 } 10 } 11 return newArr; 12 }輸出 newArr 結果:
tip: Map 是一種新的數據類型,類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當作鍵。可以把它想象成key類型沒有限制的對象。它的存取使用單獨的get()、set()接口。?
?
方法二:Set?(11)
1 function unique(arr){ 2 var set = new Set(arr); 3 return Array.from(set); 4 }輸出 newArr 結果:?
tip:Set 是一種新的數據結構。它類似于數組,但是成員的值都是唯一的,沒有重復的值。Array.from()?方法從類似數組或可迭代對象創建一個新的數組實例。
?
想要具體了解 Set 和 Map ,查看?http://wiki.jikexueyuan.com/project/es6/set-map.html
?
方法三:Array.prototype.includes()?(12)
1 function unique(arr) { 2 var newArr = []; 3 arr.forEach(function(item){ 4 if(!newArr.includes(item)){ 5 newArr.push(item); 6 } 7 }); 8 return newArr; 9 }?輸出 newArr 結果:?
?
二、NaN 等類型數據的去重:
使用測試用例,對上面所有算法進行驗證 (以 黃色數字 為測試順序)
1 var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/] 2 3 console.log(unique(arr));?
得到結果如下:
?
tips:
?
That's all ~
?
?
學習并感謝:
總結
以上是生活随笔為你收集整理的这么全的数组去重,你怕不怕?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RxAndroid2 / RxJava2
- 下一篇: msm(CentOS 6)及jvm虚拟机