1、利用for嵌套for,然后splice去重
let arr = [1, 3, 7, 10, 10, 1, true,true,false,'true',null,{a:'1'},{a:'1'}, null,undefined,undefined,NaN,NaN]; for (let i = 0; i < arr.length; i++) { for (let j = i + 1; j < arr.length; j++) { // 第一個數與比后面的數比較 if (arr[i] === arr[j]) { arr.splice(j, 1); // 刪除與第一個數比相等的數 i--; // 因為刪除了需要重新比較 } } } console.log(arr);//[1, 3, 7, 10, true, false,'true', null, { a: '1' }, { a: '1' },undefined, NaN,NaN]
//這種方法利用了雙層循環,外層循環元素,內層循環時比較值,如果值相同時則刪除這個值, //同時這個方法會改變原數組
這種方法沒有把對象類型和NaN重復的遍歷掉
2、indexOf去重,也是最常用的
let arr = [1, 3, 7, 10, 10, 1, true,true,false,'true',null,{a:'1'},{a:'1'}, null,undefined,undefined,NaN,NaN]; let temp =[]; for(let i = 0 ; i < arr.length; i++){ if(temp.indexOf(arr[i]) === -1){ // temp.indexOf(arr[i]) 通過數組的下標查找沒有查找的值,始終為-1 temp.push(arr[i]); // temp數組沒有相同的值,就加入數組。反之 } } console.log(temp);//[1, 3, 7, 10, true, false,'true', null, { a: '1' }, { c: '1' },undefined, NaN,NaN] //這個方法不會改變原數組,這時候需要創建一個新數組,利用數組的indexOf方法判斷新數組里面是否有原數組的元素,當返回結果是-1時,證明該元素不存在新數組內,再將元素添加到新的數組里面。
這種方法也沒有把對象類型和NaN重復的遍歷掉 ,原因是indexOf
方法有兩個缺點,一是不夠語義化,它的含義是找到參數值的第一個出現位置,所以要去比較是否不等於-1
,表達起來不夠直觀。二是,它內部使用嚴格相等運算符(===
)進行判斷,這會導致對NaN
的誤判。
3、利用includes去重
let arr = [1, 3, 7, 10, 10, 1,"A",'A',true,true,false,'true',null,{a:'1'},{a:'1'},null,undefined,undefined,NaN,NaN]; let temp = []; for(let item of arr){ if(temp.includes(item) == false){ // 通過遍歷的值,去查找新數組是否有該值,返回的是false就沒有,加入新數組。反之 temp.push(item); } } console.log(temp);//[1, 3, 7, 10, ,'A',true, false,'true', null, { a: '1' }, { a: '1' },undefined, NaN]
則同上一個indexOf方法相比就沒有這個問題。但是對象還是不能被遍歷掉
[NaN].includes(NaN)// true
4、利用new set()方法去重
//對象不能被遍歷掉 let arr = [{a:1}, {a:2}, {a:2}, {a:3},1,1,2,2,3,5,5,NaN,NaN]; //[{a:1},{a:2},{a:2},{a:3},1,2,3,5] let set = new Set(arr); let newArr = Array.from(set); console.log(newArr); //[{a:1},{a:2},{a:2},{a:3},1,2,3,5,NaN] //這種時候對象可以被遍歷掉,並且NaN也可以過濾掉 const b={a:2} let arr = [{a:1}, b, b, {a:3},NaN,NaN,1,1,2,2,3,5,5]; //[{a:1},{a:2},{a:2},{a:3},1,2,3,5] let set = new Set(arr);//去掉重復數據,返回結果是'set' let newArr = Array.from(set); //將set轉化為數組 console.log(newArr); // [ { a: 1 }, { a: 2 }, { a: 3 }, NaN ,1,2,3,5]
Set類似於數組,區別在於它所有的成員都是唯一的,不能有重復的值
5、利用數組中的filter方法
let arr = [1, 3, 7, 10, 10, 1,"A",'A',true,true,false,'true',null,{a:'1'},{a:'1'},null,undefined,undefined,NaN,NaN]; let result = arr.filter(function(value,index,self){ return self.indexOf(value) == index; // 數組中的每個元素執行相同的函數,將結果組合成一個新數組。 }) console.log(result)
利用數組中的filter方法.filter()接收的回調函數,其實可以有多個參數。通常我們僅使用第一個參數element,表示Array的某個元素。回調函數還可以接收另外兩個參數,表示元素的位置index和數組本身self.
filter()把傳入的函數依次作用於每個元素,然后根據返回值是true還是false決定保留還是丟棄該元素。
filter去除重復元素依靠的是indexOf總是返回第一個元素的位置,后續的重復元素位置與indexOf返回的位置不相等,因此被filter濾掉了。但此時NaN則全被過濾掉
6、利用Map數據結構去重
let arr = [1, 3, 7, 10, 10, 1,"A",'A',true,true,false,'true',null,{a:'1'},{a:'1'},null,undefined,undefined, NaN,NaN,NaN]; let map = new Map(); // 利用Map的數據結構去重 let temp = []; for (let i = 0; i < arr.length; i++) { if (!map.has(arr[i])) {//has進行值得查找,返回true或false map.set(arr[i], true); temp.push(arr[i]); } } console.log(temp);//[1,3,7,10,'A',true,false,'true', null,{ a: '1' },{ a: '1' }, undefined, NaN]
創建一個空Map數據結構,遍歷需要去重的數組,把數組的每一個元素作為key存到Map中。由於Map中不會出現相同的key值,所以最終得到的就是去重后的結果。
7、利用hasOwnProperty
function unique(arr) { var obj = {}; return arr.filter(function(item, index, arr){ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) }) } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] //所有的都去重了
hasOwnProperty是js中唯一可以判斷一個屬性定義在對象本身而不是繼承原型鏈的方法,主要用於判斷某個對象中是否有某個屬性,返回值為布爾值
8、利用遞歸去重.
function unique(arr) { var array= arr; var len = array.length; array.sort(function(a,b){ //排序后更加方便去重 return a - b; }) function loop(index){ if(index >= 1){ if(array[index] === array[index-1]){ array.splice(index,1); } loop(index - 1); //遞歸loop,然后數組去重 } } loop(len-1); return array; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]
這種方法也沒有將NaN和對象遍歷掉
最后總結:正常number和字符串類型以上幾種方法都能遍歷掉, 而只有第三、四、五、六、七種方法將NaN值過濾掉了,而同時能把對象值遍歷掉的只有第四和第七種方法去判斷對象中是否存在某個相同屬性,然后遍歷掉,得到去重后的效果。還有大家如果有更好的數組去重效果可以補充,互相學習進步