欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript實現(xiàn)數(shù)組去重的14種方法大全

 更新時間:2025年03月12日 09:58:09   作者:儒雅的烤地瓜  
親愛的小伙伴,對于數(shù)組javascript中的數(shù)組去重方法你知道多少種呢?學(xué)會如何對數(shù)組進(jìn)行去重對于javascript的學(xué)習(xí)來說也是十分重要的,下邊就讓我來分享一下我所知道的集中數(shù)組去重的方法吧,感興趣的小伙伴跟著小編一起來看看吧

一、利用for循環(huán)嵌套去重

var array = [ 0, 0, 1, 1, '1', '1', 'true', 'true', true, true, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 'a', 'a', {}, {}, { a: 1 }, { b: 2 }, { a: 1 }];
 
function unique(array) {
    // res用來存儲結(jié)果
    var res = [];
    for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {
        for (var j = 0, resLen = res.length; j < resLen; j++ ) {
            if (array[i] === res[j]) {
                break;
            }
        }
        // 如果array[i]是唯一的,那么執(zhí)行完循環(huán),j等于resLen
        if (j === resLen) {
            res.push(array[i])
        }
    }
    return res;
}
// NaN 和 對象 無法去重
console.log(unique(array)); 
// [0, 1, '1', 'true', true, false, undefined, null, NaN, NaN, 'NaN', 'a', {…}, {…}, {…}, {…}, {…}]


輸出結(jié)果:NaN 和 對象 無法去重,其他都可以去重(包括null)

我的結(jié)論:for循環(huán) 判斷依據(jù)是全等===——值和類型都相同,才去重

二、利用splice() + for循環(huán)嵌套(ES5中最常用)

利用for循環(huán)嵌套,然后splice去重:將數(shù)組中的每一個元素依次與其他元素作比較,發(fā)現(xiàn)重復(fù)元素,刪除。

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
function unique(arr) {
  for (var i = 0; i < arr.length; i++) {
    for (var j = i + 1; j < arr.length; j++) {
      if (arr[i] == arr[j]) {
        //如果第一個等同于第二個,splice方法刪除第二個
        arr.splice(j, 1);
 
        j--;
      }
    }
  }
  return arr;
}
 
console.log(arr[4],typeof arr[4],arr[6],typeof arr[6]) // true string true boolean
console.log(arr[4]==1,arr[6]==1) // false true
 
// NaN 和 {} 沒有去重,且兩個 null 直接消失了
// 如果第一個等同于第二個,splice方法刪除第二個,所以1跟'1'、true留1,false跟0留false
console.log(unique(arr)); // [1, 2, 'true', 15, false, undefined, NaN, NaN, 'NaN', 'a', {…}, {…}, {…}, {…}, {…}]

雙層循環(huán),外層循環(huán)元素,內(nèi)層循環(huán)時比較值。值相同時,則刪去這個值。

輸出結(jié)果:NaN 和 對象 無法去重,且null會被忽略掉,直接消失了

我的結(jié)論:splice() 判斷依據(jù)是值等==——值相同

字符串類型的數(shù)字、boolean類型:true、false,比較時會轉(zhuǎn)為number類型的數(shù)字

三、利用indexOf() + for循環(huán)去重

indexOf() 方法可返回數(shù)組中某個指定的元素位置。
該方法將從頭到尾地檢索數(shù)組,看它是否含有對應(yīng)的元素。開始檢索的位置在數(shù)組 start 處或數(shù)組的開頭(沒有指定 start 參數(shù)時)。如果找到一個 item,則返回 item 的第一次出現(xiàn)的位置。開始位置的索引為 0。
如果在數(shù)組中沒找到指定元素則返回 -1。
提示:如果你想查找字符串最后出現(xiàn)的位置,請使用 lastIndexOf() 方法。

新建一個空的結(jié)果數(shù)組,for 循環(huán)原數(shù)組,判斷結(jié)果數(shù)組是否存在當(dāng)前元素,如果有相同的值則跳過,不相同則push進(jìn)數(shù)組。

輸出結(jié)果:NaN 和 對象 無法去重,indexOf() 方法無法識別數(shù)組的 NaN 和 {} 成員。

我的結(jié)論:indexOf() 判斷依據(jù)是全等===——值和類型都相同,才去重

四、利用sort() + for循環(huán)去重

sort() 方法用于對數(shù)組的元素進(jìn)行排序。

排序順序可以是字母或數(shù)字,并按升序或降序。

? 默認(rèn)排序順序為按字母升序。

注意:當(dāng)數(shù)字是按字母順序排列時"40"將排在"5"前面。

? 使用數(shù)字排序,你必須通過一個函數(shù)作為參數(shù)來調(diào)用。

函數(shù)指定數(shù)字是按照升序還是降序排列。

注意: 這種方法會改變原始數(shù)組!

利用sort()排序方法,然后根據(jù)排序后的結(jié)果進(jìn)行遍歷及相鄰元素比對。 

var array = [1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
function unique(array) {
    if(!Array.isArray(array)) {
        console.log('type error');
        return;
    }
    arr = array.sort(); // 對array進(jìn)行排序,sort()會改變原數(shù)組
    var arrys = [arr[0]]; // 新建一個數(shù)組,用于存放不包含重復(fù)元素的數(shù)組
    for(var i = 1; i < arr.length; i++) {
        if(arr[i] != arr[i-1]) {
            arrys.push(arr[i]);
        }
    }
    return arrys;
}
// NaN 和 對象 無法去重,其他都可以去重(包括null)
console.log(unique(array)); // [0, 1, 15, 2, NaN, NaN, 'NaN', {…}, {…}, {…}, {…}, {…}, 'a', false, null, 'true', true, undefined]

輸出結(jié)果:NaN 和 對象 無法去重,其他都可以去重(包括null)

我的結(jié)論:sort()  判斷依據(jù)是全等===——值和類型都相同,才去重

五、利用includes() + for循環(huán)去重(ES7)

includes() 方法用來判斷一個數(shù)組是否包含一個指定的值,如果是返回 true,否則false。

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
function unique(arr) {
  if (!Array.isArray(arr)) {
    console.log("type error!");
    return;
  }
 
  var array = [];
  for (var i = 0; i < arr.length; i++) {
    if (!array.includes(arr[i])) { // includes 檢測數(shù)組是否有某個值
      array.push(arr[i]);
    }
  }
  return array;
}
 
// 對象 無法去重,其他都可以去重(包括NaN、null)
console.log(unique(arr)); // [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]

輸出結(jié)果:對象 無法去重,其他都可以去重(包括NaN、null)

我的結(jié)論:includes() 判斷依據(jù)是全等===——值和類型都相同,才去重

PS:JavaScript String 對象也有 includes() 方法。

includes() 方法用于判斷字符串是否包含指定的子字符串。如果找到匹配的字符串則返回 true,否則返回 false。

注意:JavaScript String 對象的 includes() 方法區(qū)分大小寫。

六、利用Object鍵值對及其hasOwnProperty()去重

? hasOwnProperty方法

hasOwnProperty() 方法是 Object 的原型方法(也稱實例方法),它定義在 Object.prototype 對象之上,所有 Object 的實例對象都會繼承 hasOwnProperty() 方法。

hasOwnProperty() 方法用來檢測一個屬性是否是對象的自有屬性,而不是從原型鏈繼承的。如果該屬性是自有屬性,那么返回 true,否則返回 false。

換句話說,hasOwnProperty() 方法不會檢測對象的原型鏈,只會檢測當(dāng)前對象本身,只有當(dāng)前對象本身存在該屬性時才返回true。

用法:object.hasOwnProperty(propertyName)  ,參數(shù)propertyName指要檢測的屬性名;

? Object 鍵值對:var obj = {...}

—— 如何實現(xiàn)去重 ——

1、通過 filter 為數(shù)組的每一個元素做條件過濾。

2、再通過 三元運算 將數(shù)組的元素作為key登記在obj中,將它對應(yīng)的值設(shè)為true。

3、通過 hasOwnProperty 判斷對象是否包含某一屬性(鍵),如果包含即返回false, filter 接收到false將會過濾掉該 item (array[index]) 的return事件。

Object 鍵值對這種方法是利用一個空的 Object 對象,我們把數(shù)組的值存成 Object 的 key 值,比如 Object[value1] = true,在判斷另一個值的時候,如果 Object[value2]存在的話,就說明該值是重復(fù)的。示例代碼如下:

var array = [1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array){
        return obj.hasOwnProperty(item) ? false : (obj[item] = true)
    })
}
// 可去重同值不同類型的項,但對象 無法去重,且原數(shù)組中除第一個對象外,所有對象都會被去(忽略)掉;
console.log(unique(array)); // [1, 2, 'true', 15, false, undefined, null, NaN, 0, 'a', {…}]


輸出結(jié)果:Object 鍵值對方法的有2個bug還會去重同值不同類型的項,且無法去重(區(qū)分)多個對象,即原數(shù)組中除第一個對象可以去重外,所有對象都會被去(忽略)掉,

缺點總結(jié):

bug - 1 會去重同值不同類型的項

由于Object的鍵只能是String類型,因此 obj[1] 與 obj['1'] 以及 obj['true'] 與 obj[true]、obj[NaN] 與 obj['NaN'] 是等價的,它們引用同一個堆棧,最終在第二數(shù)組實參中 1 和 '1' 、'true' 和 true、NaN 和 'NaN' 被去重為同一個元素。

bug -2 原數(shù)組中除第一個對象可以去重外,所有對象都會被去(忽略)掉  ——無法去重多個對象

改進(jìn)1.0:typeOf - 升級版

分析:我們可以發(fā)現(xiàn),由于Object的鍵只能是String類型,這樣做是有問題的,因為 1 和 '1' 是不同的,但是這種方法會判斷為同一個值,這是因為對象的鍵值只能是字符串,所以我們可以通過使用 typeof item + item 的方式拼成一個字符串,來作為obj的 key 值來避免這個問題

var arr = [1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{}];
 
function unique(arr) {
  var obj = {};
  return arr.filter(function (item, index, arr) {
    // 使用typeof item+item拼成一個字符串,來作為 hasOwnProperty 的判斷依據(jù)以及obj的key值
    return obj.hasOwnProperty(typeof item + item)
      ? false
      : (obj[typeof item + item] = true);
  });
}
// 都可以去重,包括NaN、null、{}(僅限數(shù)組中的一個對象,如有其他對象都會被去掉)
console.log(unique(arr)); // [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}]


輸出結(jié)果:升級版存在1個bug:無法去重(區(qū)分)多個對象,即原數(shù)組中除第一個對象可以去重外,所有對象都會被去(忽略)掉;

缺點總結(jié):無法去重(區(qū)分)多個對象

bug - 對象去重,僅限原數(shù)組中的第一個對象,其他所有對象都會被去(忽略)掉;

如果數(shù)組中存在多個對象,除了數(shù)組中的第一個對象,所有的對象都會被過濾(不管該對象是否重復(fù)都會被去掉)。 

——分析去重過程 ——

使用filter函數(shù),過濾出一個新數(shù)組,也就是最終的去重后的數(shù)組。

三元表達(dá)式,主要是為了得到判斷結(jié)果:true或false,然后return這個true或false這個結(jié)果,以便filter函數(shù)過濾出一個不包含重復(fù)項的新數(shù)組

① 當(dāng)obj.hasOwnProperty(typeof item + item)為 false 時,說明obj對象中不存在(typeof item + item)這個自有屬性,也就是說當(dāng)前循環(huán)的arr中的item項的值,沒有讓typeof item + item成為obj的私有屬性,obj不存在(typeof item + item)這個屬性

此時,整個三元表達(dá)式的值為(obj[typeof item + item] = true),整個值的真假(true 或 flase)決定了filter函數(shù)當(dāng)前循環(huán)的item值是否能成為filter過濾出的新數(shù)組的元素。

因為目前obj中不存在(typeof item + item)這個自有屬性,所以obj[ typeof item + item ] =undefined,所以undefined = true為true,說明當(dāng)前循環(huán)的arr中的item項,符合條件,會加入filter函數(shù)過濾后的新數(shù)組

② 當(dāng)obj.hasOwnProperty(typeof item + item)為 true 時,說明obj對象中已存在(typeof item + item)這個自有屬性,

此時,三元表達(dá)式的值為false,說明當(dāng)前循環(huán)的arr中的item項,不符合條件,不會加入filter函數(shù)過濾后的新數(shù)組

舉個例子:array[0]和array[4]分別被 typeof 拼接成 "number1" 和 "stringtrue",很好的區(qū)分了不同類型轉(zhuǎn)字符串后的區(qū)別

但是如果數(shù)組中存在對象,比如[ { name: 97 }, { descript: 'z' } ],由于 typeof item + item 的結(jié)果都會是 object[object Object] (String類型),所以除了數(shù)組中的第一個對象,所有的對象都會被過濾(不重復(fù)的對象也會被去掉)

改進(jìn)2.0 :JSON.stringify() - 終極解決方案!

然而,即便如此,我們依然無法正確區(qū)分出兩個對象,比如 {value: 1} 和 {value: 2},因為 object[typeof item + item] 的結(jié)果都會是 object[object Object],所以我們可以使用 JSON.stringify() 將對象序列化,來避免相同的鍵值對。

let arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
let obj={}
 
let result=arr.filter((item)=>{
   return obj.hasOwnProperty(
   //因為JSON.stringify(NaN)==null,所以先檢測是否為數(shù)字類型,數(shù)字類型直接返回,否則再JSON.stringify
    typeof item=="number"?item:JSON.stringify(item))?
    false:(obj[typeof item=="number"?item:JSON.stringify(item)]=1);
})
 
// 全都可以去重,完美解決方案!
console.log(result) // [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {}, {a:1}, {b:2}]


輸出結(jié)果:全都可以去重,無bug,完美解決方案! 

我的結(jié)論:Object鍵值對 + hasOwnProperty() + typeOf + JSON.stringify() 判斷依據(jù)是全等===——值和類型都相同,才去重

七、利用filter() + indexOf()去重

用法:array.indexOf(item,start) 

start:可選的整數(shù)參數(shù)。規(guī)定在數(shù)組中開始檢索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略該參數(shù),則將從字符串的首字符開始檢索。

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN,NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
function unique(arr) {
  return arr.filter(function (item, index, arr) {
    //當(dāng)前元素,在原始數(shù)組中的第一個索引==當(dāng)前索引值,否則返回當(dāng)前元素
    return arr.indexOf(item, 0) === index;
  });
}
// 
console.log(unique(arr)); // [1, 2, '1', 'true', true, 15, false, undefined, null, 'NaN', 0, 'a', {} , {} , {a:1} , {b:2} , {a:1}]

輸出結(jié)果:對象 無法去重,且NaN會被去(忽略)掉,直接消失了,其他都可以去重,包括null。indexOf() 方法無法識別數(shù)組的 NaN 和 {} 成員。

我的結(jié)論:filter() 判斷依據(jù)是全等===——值和類型都相同,才去重

八、利用遞歸去重

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
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,然后數(shù)組去重
    }
  }
  loop(len - 1);
  return array;
}
// 
console.log(unique(arr)) // [1, '1', true, 2, 'true', false, null, 0, true, 15, NaN, NaN, 'NaN', 'a', {…}, {…}, {…}, {…}, {…}, undefined]

輸出結(jié)果:NaN 和 對象 無法去重,其他都可以實現(xiàn)去重,包括null。indexOf() 方法無法識別數(shù)組的 NaN 和 {} 成員。

我的結(jié)論:遞歸去重法的判斷依據(jù)是全等===——值和類型都相同,才去重

九、利用Set數(shù)據(jù)結(jié)構(gòu)(ES6)

隨著 ES6 的到來,去重的方法又有了進(jìn)展,比如我們可以使用 Set 和 Map 數(shù)據(jù)結(jié)構(gòu),以 Set 為例,ES6 提供了新的數(shù)據(jù)結(jié)構(gòu) Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。Set 本身是一個構(gòu)造函數(shù),用來生成 Set 數(shù)據(jù)結(jié)構(gòu)。

因為Set是一個類似數(shù)組結(jié)構(gòu),所以需要用 Array.from() 方法解析類數(shù)組為數(shù)組,將其轉(zhuǎn)型為真正的數(shù)組去使用。Array.from 方法可以將 Set 結(jié)構(gòu)轉(zhuǎn)為數(shù)組。

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
function unique (arr) {
  return Array.from(new Set(arr))
}
// 對象 無法去重,會被保留下來,但可對 NaN、null 去重
console.log(unique(arr)) 
//[1, 2, '1', "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {} , {a:1} , {b:2} , {a:1}]

甚至可以再簡化下:語法糖——復(fù)制一個數(shù)組: var arr2=[...arr1]

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
function unique(arr) {
    // 利用 [...new Set(arr)] 轉(zhuǎn)為數(shù)組后去重
    return [...new Set(arr)];
}
console.log(unique(arr));
// [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]

還可以再簡化下:轉(zhuǎn)為ES6 箭頭函數(shù)

var arr = [1, 1, 2, '1', 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}, { a: 1 }, { b: 2 }, { a: 1 }];
 
var unique = (arr) => [...new Set(arr)]
 
console.log(unique(arr));
// (18) [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]

注:不考慮兼容性,這種使用Set數(shù)據(jù)結(jié)構(gòu)去重的方法代碼最少。而且這種方法還無法去重對象,不過可以對NaN、null進(jìn)行去重,因為 Set 加入值時認(rèn)為NaN等于自身,后面的高階方法會添加去掉重復(fù)“{}”的方法。

輸出結(jié)果:對象 無法去重,其他都可以實現(xiàn)去重,包括NaN、null 

我的結(jié)論:newSet() 判斷依據(jù)是全等===——值和類型都相同,才去重

十、利用Map數(shù)據(jù)結(jié)構(gòu)去重(ES6

了解Map數(shù)據(jù)結(jié)構(gòu)

Map數(shù)據(jù)結(jié)構(gòu)。它類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當(dāng)作鍵。也就是說,Object結(jié)構(gòu)提供了“字符串—值”的對應(yīng),Map 結(jié)構(gòu)提供了“值—值”的對應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實現(xiàn)。

Map 與 Object 的區(qū)別:Object里的屬性是字符串;Map里的key可以是任意的數(shù)據(jù)類型 key:value

對Map來說,我們可以通過使用set,get,has,delete等方法來對Map進(jìn)行操作

創(chuàng)建一個空Map數(shù)據(jù)結(jié)構(gòu),遍歷需要去重的數(shù)組,把數(shù)組的每一個元素作為key存到Map中,由于Map中不會出現(xiàn)相同的key值,所以,最終得到的就是去重后的結(jié)果。

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
 
function unique(arr) {
  // Map與Object的區(qū)別 Object里的屬性是字符串;Map里的key可以是任意的數(shù)據(jù)類型 key:value
  let map = new Map();
  let array = new Array(); // 數(shù)組用于返回結(jié)果
  for (let i = 0; i < arr.length; i++) {
    // has方法返回一個布爾值,表示某個鍵是否在當(dāng)前 Map 對象之中。
    if (map.has(arr[i])) { // 如果有該key值
      // set方法設(shè)置鍵名key對應(yīng)的鍵值為value,然后返回整個 Map 結(jié)構(gòu)。如果key已經(jīng)有值,則鍵值會被更新,否則就新生成該鍵。
      map.set(arr[i], true);
    } else {
      map.set(arr[i], false); // 如果沒有該key值
      array.push(arr[i]);
    }
  }
  return array;
}
// 
console.log(unique(arr)) 
// [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]


輸出結(jié)果:對象 無法去重,其他都可以實現(xiàn)去重,包括NaN、null 

我的結(jié)論:Map數(shù)據(jù)結(jié)構(gòu)去重法 判斷依據(jù)是全等===——值和類型都相同,才去重

十一、利用Map數(shù)據(jù)結(jié)構(gòu) + filter()

var arr = [1, 1, 2, '1', 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}, { a: 1 }, { b: 2 }, { a: 1 }];
 
function unique(arr) {
  const seen = new Map()
  return arr.filter((item) => !seen.has(item) && seen.set(item, 1))
}
 
console.log(unique(arr));
// [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]


輸出結(jié)果:對象 無法去重,其他都可以實現(xiàn)去重,包括NaN、null 

我的結(jié)論:Map數(shù)據(jù)結(jié)構(gòu)去重法 判斷依據(jù)是全等===——值和類型都相同,才去重

十二、利用reduce() + includes()去重

Array.reduce 為數(shù)組的歸并方法,使用場景很多,比如求和(累加)、求乘積(累乘),計次,去重,多維轉(zhuǎn)一維,屬性求和等...

var arr=[1,1,2,'1','true','true',true,true,15,15,false,false,undefined,undefined,null,null,NaN, NaN,'NaN',0,0,'a','a',{},{},{a:1},{b:2},{a:1}];
function unique(arr) {
  return arr.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []);
}
 
// 對象 無法去重
console.log(unique(arr));
// [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]

輸出結(jié)果:對象 無法去重,其他都可以實現(xiàn)去重,包括NaN、null 

我的結(jié)論:reduce() + includes()去重法 判斷依據(jù)是全等===——值和類型都相同,才去重

十三、利用findIndex() + Object.is()去重

—— findIndex() ——

findIndex() 方法返回傳入一個測試條件(函數(shù))符合條件的數(shù)組第一個元素位置。

findIndex() 方法為數(shù)組中的每個元素都調(diào)用一次函數(shù)執(zhí)行:

  • 當(dāng)數(shù)組中的元素在測試條件時返回 true 時, findIndex() 返回符合條件的元素的索引位置,之后的值不會再調(diào)用執(zhí)行函數(shù)。
  • 如果沒有符合條件的元素返回 -1

注意: findIndex() 對于空數(shù)組,函數(shù)是不會執(zhí)行的。

注意: findIndex() 并沒有改變數(shù)組的原始值。

—— Object.is() ——

Object.is() 方法用來判斷兩個值是否相等,它接收兩個參數(shù),分別是需要比較的兩個值。

返回一個 Boolean 值表示這兩個值是否相等。

var arr = [1, 1, 2, '1', 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {}, {}, { a: 1 }, { b: 2 }, { a: 1 }];
 
function unique(arr) {
  let result = [];
  for (let i = 0; i < arr.length; i++) {
    // Object.is()方法認(rèn)為NaN等于自身
    if (result.findIndex(value => Object.is(arr[i],value)) === -1) {
      result.push(arr[i]);
    }
  }
  return result;
}
// 
console.log(unique(arr));

輸出結(jié)果:對象 無法去重,其他都可以實現(xiàn)去重,包括NaN、null 

我的結(jié)論:reduce() + includes()去重法 判斷依據(jù)是全等===——值和類型都相同,才去重

十四、對象數(shù)組去重 

方法一:使用Map數(shù)據(jù)結(jié)構(gòu)

Map是一組鍵值對的結(jié)構(gòu),用于解決以往不能用對象做為鍵的問題,具有極快的查找速度。(注:函數(shù)、對象、基本類型都可以作為鍵或值。

const ary = [{id: 1, text: "1"}, {id: 1, text: "1"}, {id: 2, text: "2"}, {id: 3, text: "3"}];
 
const myseta = (ary) => {
  const map = new Map();
  return ary.filter((ary) => !map.has(ary.id) && map.set(ary.id, 1))
};
 
console.log(myseta(ary)); // [{id: 1, text: '1'}, {id: 2, text: '2'}, {id: 3, text: '3'}]

方法二:使用Set數(shù)據(jù)結(jié)構(gòu)

JSON.stringify + new Set( ) + Array.from() + JSON.parse

使用Set數(shù)據(jù)結(jié)構(gòu)去除重復(fù)對象,必須把對象轉(zhuǎn)為string字符串形式,才可以實現(xiàn)對象去重,所以需要new Set(strings)進(jìn)行轉(zhuǎn)型。

因為Set數(shù)據(jù)結(jié)構(gòu)并非真正的數(shù)組,它類似于數(shù)組,并且成員值都是唯一的,沒有重復(fù),所以可以用來做去重操作。但是因為它是一個類似數(shù)組結(jié)構(gòu),所以需要轉(zhuǎn)型為真正的數(shù)組去使用。所以,需要用Array.from

const ary = [{id: 1, text: "1"}, {id: 1, text: "1"}, {id: 2, text: "2"}, {id: 3, text: "3"}];
const myseta = (ary) => {
  const strings = ary.map((item) => JSON.stringify(item))
  // 使用Set數(shù)據(jù)結(jié)構(gòu)去重對象
  // return new Set(strings)
 
  // 使用Array.from()把Set數(shù)據(jù)結(jié)構(gòu)去重對象后的結(jié)構(gòu),轉(zhuǎn)為數(shù)組
  // return Array.from(new Set(strings))
 
  // 使用Array.from()轉(zhuǎn)為數(shù)組,然后再使用數(shù)組的map方法把數(shù)組里面的字符串類型轉(zhuǎn)化為對象類型:
  return Array.from(new Set(strings)).map((item) => JSON.parse(item))
 
};
 
// console.log(myseta(ary)); // Set(3) {'{"id":1,"text":"1"}', '{"id":2,"text":"2"}', '{"id":3,"text":"3"}'}
// console.log(myseta(ary)); // ['{"id":1,"text":"1"}', '{"id":2,"text":"2"}', '{"id":3,"text":"3"}']
console.log(myseta(ary)); // [{"id":1,"text":"1"}', '{"id":2,"text":"2"}', '{"id":3,"text":"3"}]

定義和用法

map() 方法返回一個新數(shù)組,數(shù)組中的元素為原始數(shù)組元素調(diào)用函數(shù)處理后的值。

map() 方法按照原始數(shù)組元素順序依次處理元素。

注意: map() 不會對空數(shù)組進(jìn)行檢測。

注意: map() 不會改變原始數(shù)組。

方法總結(jié)

如果有如下這樣一個數(shù)組 :

var arr = [ 0, 0, 1, 1, '1', '1', 'true', 'true', true, true, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 'a', 'a', new String('1'), new String('1'), /a/, /a/, {}, {}, { a: 1 }, { b: 2 }, { a: 1 }];

由于各去重方法的兼容性不同,所得到的去重結(jié)果就會有所有不同,下面來查看一下各方法的兼容性差異: 

方法結(jié)果說明
for循環(huán)[0, 1, '1', 'true', true, false, undefined, null, NaN, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?NaN 和 對象、正則、構(gòu)造函數(shù)不去重;
splice() + for循環(huán)[0, 1, 'true', undefined, NaN, NaN, 'NaN', 'a', /a/, /a/, {…}, {…}, {…}, {…}, {…}]?NaN 和 對象、正則不去重;null、構(gòu)造函數(shù)被忽略掉;字符串?dāng)?shù)字、boolean的true、false轉(zhuǎn)為數(shù)字
indexOf() + for循環(huán)[0, 1, '1', 'true', true, false, undefined, null, NaN, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?NaN 和 對象、正則、構(gòu)造函數(shù)不去重;
sort() + for循環(huán)[/a/, /a/, 0, 1, String, NaN, NaN, 'NaN', {…}, {…}, {…}, {…}, {…}, 'a', false, null, 'true', true, undefined]?NaN 和 對象、正則不去重;new String('1') 和 ‘1’等價,所以會去重
includes() [0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重
優(yōu)化后的鍵值對方法[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', /a/, {…}, {…}]?全去重,完美解決方案!
filter()+indexOf()[0, 1, '1', 'true', true, false, undefined, null, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重;NaN會被忽略掉
遞歸[0, false, null, 1, '1', 'true', true, NaN, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}, undefined]?NaN 和 對象、正則、構(gòu)造函數(shù)不去重;
Set數(shù)據(jù)結(jié)構(gòu)[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重;
Map數(shù)據(jù)結(jié)構(gòu)[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重;
Map數(shù)據(jù)結(jié)構(gòu) + filter()[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重;

reduce() + includes()

[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重;
findIndex() + Object.is()[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對象、正則、構(gòu)造函數(shù)不去重;

注意:上述表格的說明部分,除了不去重的、被去重跳過忽略掉的之外,其他的都可以實現(xiàn)去重,包括null、NaN(當(dāng)然,僅限在去重數(shù)組范圍內(nèi)的項,不在測試去重數(shù)組范圍內(nèi)其他類型數(shù)據(jù),大家可自行測試。),以上方法的整理總結(jié),如有錯誤之處,還請大家評論指出!

寫在最后

雖然各個方法去重的結(jié)果有所不同,但更重要的是讓我們知道在合適的場景要選擇合適的去重方法。

另外,還有很多文章提到其他去重的方法,比如,foreach + indexOf 數(shù)組去重的方法,不過,實現(xiàn)的過程,個人覺得都是大同小異。如果還有其他比較好的去重方法,歡迎評論給出!

以上就是JavaScript實現(xiàn)數(shù)組去重的14種方法大全的詳細(xì)內(nèi)容,更多關(guān)于JavaScript數(shù)組去重的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論