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