亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

一、利用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用來(lái)存儲(chǔ)結(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 和 對(duì)象 無(wú)法去重
console.log(unique(array)); 
// [0, 1, '1', 'true', true, false, undefined, null, NaN, NaN, 'NaN', 'a', {…}, {…}, {…}, {…}, {…}]


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

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

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

利用for循環(huán)嵌套,然后splice去重:將數(shù)組中的每一個(gè)元素依次與其他元素作比較,發(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]) {
        //如果第一個(gè)等同于第二個(gè),splice方法刪除第二個(gè)
        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 和 {} 沒有去重,且兩個(gè) null 直接消失了
// 如果第一個(gè)等同于第二個(gè),splice方法刪除第二個(gè),所以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)時(shí)比較值。值相同時(shí),則刪去這個(gè)值。

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

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

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

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

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

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

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

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

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

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

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

? 默認(rèn)排序順序?yàn)榘醋帜干颉?/strong>

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

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

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

注意: 這種方法會(huì)改變?cè)紨?shù)組!

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

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(); // 對(duì)array進(jìn)行排序,sort()會(huì)改變?cè)瓟?shù)組
    var arrys = [arr[0]]; // 新建一個(gè)數(shù)組,用于存放不包含重復(fù)元素的數(shù)組
    for(var i = 1; i < arr.length; i++) {
        if(arr[i] != arr[i-1]) {
            arrys.push(arr[i]);
        }
    }
    return arrys;
}
// NaN 和 對(duì)象 無(wú)法去重,其他都可以去重(包括null)
console.log(unique(array)); // [0, 1, 15, 2, NaN, NaN, 'NaN', {…}, {…}, {…}, {…}, {…}, 'a', false, null, 'true', true, undefined]

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

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

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

includes() 方法用來(lái)判斷一個(gè)數(shù)組是否包含一個(gè)指定的值,如果是返回 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 檢測(cè)數(shù)組是否有某個(gè)值
      array.push(arr[i]);
    }
  }
  return array;
}
 
// 對(duì)象 無(wú)法去重,其他都可以去重(包括NaN、null)
console.log(unique(arr)); // [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]

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

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

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

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

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

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

? hasOwnProperty方法

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

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

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

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

? Object 鍵值對(duì):var obj = {...}

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

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

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

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

Object 鍵值對(duì)這種方法是利用一個(gè)空的 Object 對(duì)象,我們把數(shù)組的值存成 Object 的 key 值,比如 Object[value1] = true,在判斷另一個(gè)值的時(shí)候,如果 Object[value2]存在的話,就說(shuō)明該值是重復(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)
    })
}
// 可去重同值不同類型的項(xiàng),但對(duì)象 無(wú)法去重,且原數(shù)組中除第一個(gè)對(duì)象外,所有對(duì)象都會(huì)被去(忽略)掉;
console.log(unique(array)); // [1, 2, 'true', 15, false, undefined, null, NaN, 0, 'a', {…}]


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

缺點(diǎn)總結(jié):

bug - 1 會(huì)去重同值不同類型的項(xiàng)

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

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

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

分析:我們可以發(fā)現(xiàn),由于Object的鍵只能是String類型,這樣做是有問(wèn)題的,因?yàn)?1 和 '1' 是不同的,但是這種方法會(huì)判斷為同一個(gè)值,這是因?yàn)閷?duì)象的鍵值只能是字符串,所以我們可以通過(guò)使用 typeof item + item 的方式拼成一個(gè)字符串,來(lái)作為obj的 key 值來(lái)避免這個(gè)問(wè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',{},{}];
 
function unique(arr) {
  var obj = {};
  return arr.filter(function (item, index, arr) {
    // 使用typeof item+item拼成一個(gè)字符串,來(lái)作為 hasOwnProperty 的判斷依據(jù)以及obj的key值
    return obj.hasOwnProperty(typeof item + item)
      ? false
      : (obj[typeof item + item] = true);
  });
}
// 都可以去重,包括NaN、null、{}(僅限數(shù)組中的一個(gè)對(duì)象,如有其他對(duì)象都會(huì)被去掉)
console.log(unique(arr)); // [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}]


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

缺點(diǎn)總結(jié):無(wú)法去重(區(qū)分)多個(gè)對(duì)象

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

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

——分析去重過(guò)程 ——

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

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

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

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

因?yàn)槟壳皁bj中不存在(typeof item + item)這個(gè)自有屬性,所以obj[ typeof item + item ] =undefined,所以u(píng)ndefined = true為true,說(shuō)明當(dāng)前循環(huán)的arr中的item項(xiàng),符合條件,會(huì)加入filter函數(shù)過(guò)濾后的新數(shù)組

② 當(dāng)obj.hasOwnProperty(typeof item + item)為 true 時(shí),說(shuō)明obj對(duì)象中已存在(typeof item + item)這個(gè)自有屬性,

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

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

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

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

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

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(
   //因?yàn)镴SON.stringify(NaN)==null,所以先檢測(cè)是否為數(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é)果:全都可以去重,無(wú)bug,完美解決方案! 

我的結(jié)論:Object鍵值對(duì) + 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ù)組中的第一個(gè)索引==當(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é)果:對(duì)象 無(wú)法去重,且NaN會(huì)被去(忽略)掉,直接消失了,其他都可以去重,包括null。indexOf() 方法無(wú)法識(shí)別數(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 和 對(duì)象 無(wú)法去重,其他都可以實(shí)現(xiàn)去重,包括null。indexOf() 方法無(wú)法識(shí)別數(shù)組的 NaN 和 {} 成員。

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

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

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

因?yàn)镾et是一個(gè)類似數(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))
}
// 對(duì)象 無(wú)法去重,會(huì)被保留下來(lái),但可對(duì) 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}]

甚至可以再簡(jiǎn)化下:語(yǔ)法糖——復(fù)制一個(gè)數(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', {…}, {…}, {…}, {…}, {…}]

還可以再簡(jiǎn)化下:轉(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)去重的方法代碼最少。而且這種方法還無(wú)法去重對(duì)象,不過(guò)可以對(duì)NaN、null進(jìn)行去重,因?yàn)?Set 加入值時(shí)認(rèn)為NaN等于自身,后面的高階方法會(huì)添加去掉重復(fù)“{}”的方法。

輸出結(jié)果:對(duì)象 無(wú)法去重,其他都可以實(shí)現(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)。它類似于對(duì)象,也是鍵值對(duì)的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對(duì)象)都可以當(dāng)作鍵。也就是說(shuō),Object結(jié)構(gòu)提供了“字符串—值”的對(duì)應(yīng),Map 結(jié)構(gòu)提供了“值—值”的對(duì)應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實(shí)現(xiàn)。

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

對(duì)Map來(lái)說(shuō),我們可以通過(guò)使用set,get,has,delete等方法來(lái)對(duì)Map進(jìn)行操作

創(chuàng)建一個(gè)空Map數(shù)據(jù)結(jié)構(gòu),遍歷需要去重的數(shù)組,把數(shù)組的每一個(gè)元素作為key存到Map中,由于Map中不會(huì)出現(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方法返回一個(gè)布爾值,表示某個(gè)鍵是否在當(dāng)前 Map 對(duì)象之中。
    if (map.has(arr[i])) { // 如果有該key值
      // set方法設(shè)置鍵名key對(duì)應(yīng)的鍵值為value,然后返回整個(gè) Map 結(jié)構(gòu)。如果key已經(jīng)有值,則鍵值會(huì)被更新,否則就新生成該鍵。
      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é)果:對(duì)象 無(wú)法去重,其他都可以實(shí)現(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é)果:對(duì)象 無(wú)法去重,其他都可以實(shí)現(xiàn)去重,包括NaN、null 

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

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

Array.reduce 為數(shù)組的歸并方法,使用場(chǎng)景很多,比如求和(累加)、求乘積(累乘),計(jì)次,去重,多維轉(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], []);
}
 
// 對(duì)象 無(wú)法去重
console.log(unique(arr));
// [1, 2, '1', 'true', true, 15, false, undefined, null, NaN, 'NaN', 0, 'a', {…}, {…}, {…}, {…}, {…}]

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

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

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

—— findIndex() ——

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

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

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

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

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

—— Object.is() ——

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

返回一個(gè) Boolean 值表示這兩個(gè)值是否相等。

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é)果:對(duì)象 無(wú)法去重,其他都可以實(shí)現(xiàn)去重,包括NaN、null 

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

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

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

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

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ù)對(duì)象,必須把對(duì)象轉(zhuǎn)為string字符串形式,才可以實(shí)現(xiàn)對(duì)象去重,所以需要new Set(strings)進(jìn)行轉(zhuǎn)型。

因?yàn)镾et數(shù)據(jù)結(jié)構(gòu)并非真正的數(shù)組,它類似于數(shù)組,并且成員值都是唯一的,沒有重復(fù),所以可以用來(lái)做去重操作。但是因?yàn)樗且粋€(gè)類似數(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)去重對(duì)象
  // return new Set(strings)
 
  // 使用Array.from()把Set數(shù)據(jù)結(jié)構(gòu)去重對(duì)象后的結(jié)構(gòu),轉(zhuǎn)為數(shù)組
  // return Array.from(new Set(strings))
 
  // 使用Array.from()轉(zhuǎn)為數(shù)組,然后再使用數(shù)組的map方法把數(shù)組里面的字符串類型轉(zhuǎn)化為對(duì)象類型:
  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() 方法返回一個(gè)新數(shù)組,數(shù)組中的元素為原始數(shù)組元素調(diào)用函數(shù)處理后的值。

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

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

注意: map() 不會(huì)改變?cè)紨?shù)組。

方法總結(jié)

如果有如下這樣一個(gè)數(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é)果就會(huì)有所有不同,下面來(lái)查看一下各方法的兼容性差異: 

方法結(jié)果說(shuō)明
for循環(huán)[0, 1, '1', 'true', true, false, undefined, null, NaN, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?NaN 和 對(duì)象、正則、構(gòu)造函數(shù)不去重;
splice() + for循環(huán)[0, 1, 'true', undefined, NaN, NaN, 'NaN', 'a', /a/, /a/, {…}, {…}, {…}, {…}, {…}]?NaN 和 對(duì)象、正則不去重;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 和 對(duì)象、正則、構(gòu)造函數(shù)不去重;
sort() + for循環(huán)[/a/, /a/, 0, 1, String, NaN, NaN, 'NaN', {…}, {…}, {…}, {…}, {…}, 'a', false, null, 'true', true, undefined]?NaN 和 對(duì)象、正則不去重;new String('1') 和 ‘1’等價(jià),所以會(huì)去重
includes() [0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對(duì)象、正則、構(gòu)造函數(shù)不去重
優(yōu)化后的鍵值對(duì)方法[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/, {…}, {…}, {…}, {…}, {…}]?對(duì)象、正則、構(gòu)造函數(shù)不去重;NaN會(huì)被忽略掉
遞歸[0, false, null, 1, '1', 'true', true, NaN, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}, undefined]?NaN 和 對(duì)象、正則、構(gòu)造函數(shù)不去重;
Set數(shù)據(jù)結(jié)構(gòu)[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對(duì)象、正則、構(gòu)造函數(shù)不去重;
Map數(shù)據(jù)結(jié)構(gòu)[0, 1, '1', 'true', true, false, undefined, null, NaN, 'NaN', 'a', String, String, /a/, /a/, {…}, {…}, {…}, {…}, {…}]?對(duì)象、正則、構(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/, {…}, {…}, {…}, {…}, {…}]?對(duì)象、正則、構(gòu)造函數(shù)不去重;

reduce() + includes()

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

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

寫在最后

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

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

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

相關(guān)文章

最新評(píng)論