[js]從 ES3 到 ES6 教你如何數(shù)組去重

聲明

以下方法僅對數(shù)組值全部屬于 primitive data type 的情況有效。

ES6

方法一: Set數(shù)據(jù)結(jié)構(gòu) + Array.from靜態(tài)方法

ES6中新增了Set數(shù)據(jù)結(jié)構(gòu),類似于數(shù)組,但是它的成員都是唯一的 ,其構(gòu)造函數(shù)可以接受一個數(shù)組作為參數(shù),如:

 let array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3];
 let set = new Set(array);
 let deduped = Array.from(set);// `deduped = de + dup(duplication) + ed`
 console.log(deduped);
 // [1, 2, 3, 4, 5]

方法二:Set數(shù)據(jù)結(jié)構(gòu) + 擴展語法(spread syntax)

let array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3];
let deduped = [...new Set(array)];
console.log(deduped);
 // [1, 2, 3, 4, 5]

注意擴展語法對所有可遍歷對象均有效

let obj = {'key1': 'value1'};
let array = [...obj]; 
// TypeError: obj is not iterable

方法三: 箭頭函數(shù)+es5語法(filter, indexOf)

let array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3];
let deduped = array.filter((el,i,arr) => arr.indexOf(el) === i);
console.log(deduped);
 // [1, 2, 3, 4, 5]

ES5

var array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3];
var deduped = array.filter(function(el,i,arr) {
    return arr.indexOf(el) === i;
})
console.log(deduped);
 // [1, 2, 3, 4, 5]

lt_ES5

var array = [1, 1, 1, 1, 2, 3, 4, 4, 5, 3,[1,2],[3,4]];
var deduped = [];
for(var i=0, l=array.length;i<l;i++){
    var tmp = array[i];
    deduped.indexOf(tmp) === -1 && deduped.push(tmp);
}
console.log(deduped);
 // [1, 2, 3, 4, 5]

知識補充——關(guān)于indexOf

關(guān)于瀏覽器兼容性

在 IE6-8 下,數(shù)組的 indexOf 方法還不存在。
所以如果需要兼容 IE6-8,得自己造一個輪子:

var indexOf = [].indexOf ?
    function(arr, item) {
      return arr.indexOf(item)
    } :
    function indexOf(arr, item) {
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] === item) {
          return i
        }
      }
      return -1
    }

關(guān)于性能——時間復(fù)雜度

如果說利用 set 數(shù)據(jù)結(jié)構(gòu)是一種作弊的方式,那么用 indexOf 就是一種相對低下性能的方式,因為 indexOf 的底層也是一次遍歷。嵌套循環(huán)會讓追求性能極致的人感覺不爽。

① arr 遍歷push 到新數(shù)組
② 其中每循環(huán)一次調(diào)用數(shù)組的 indexOf 方法,又會是一次遍歷
所以,相當(dāng)于兩次循環(huán)嵌套,遍歷復(fù)雜度為O(n2)

這種情況下,為追求性能,更好的實現(xiàn)方式為:利用對象 key 的唯一性處理。首先將數(shù)組轉(zhuǎn)換為對象,其次將對象轉(zhuǎn)換為去重后的數(shù)組。
比如:

var songs = [
         {name:"都選C",artist:"大鵬"},
         {name:"都選C",artist:"大鵬"},
         {name:"塑料袋",artist:"喬杉"},
         {name:"塑料袋",artist:"喬杉"},
         {artist:"喬杉",name:"塑料袋"}
     ];

function unique(songs){
  let result = {};
  let finalResult=[];
  // 數(shù)組轉(zhuǎn)換為對象,利用對象key的唯一性去重
  songs.forEach(function(song, i){
    result[song.name]=song;
  })
  // 將對象還原為去重后的數(shù)組
  Object.keys(result).forEach(function(key, i){
    finalResult.push(result[key]);
  })
  
  return finalResult;
}

console.log(unique(songs));

// 注明:偷了個懶 forEach 的性能比 for 循環(huán)慢好多。
// 參考:https://github.com/jawil/blog/issues/2

2017-11-16 更新。實際上這個用了至少兩次循環(huán)(雖然不是循環(huán)嵌套),但仍然是低效的。因為最簡單的數(shù)組去重只需要用一層循環(huán)即可。

更為復(fù)雜的案例可以看筆者寫的這個demo

參考資料

https://github.com/lifesinger/blog/issues/113

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、ES6簡介 ? 歷時將近6年的時間來制定的新 ECMAScript 標(biāo)準(zhǔn) ECMAScript 6(亦稱 ...
    一歲一枯榮_閱讀 6,211評論 8 25
  • 與其說喜歡寫作,頗有點附庸風(fēng)雅之嫌,余既無文藝人士的考究,又非小資階層的閑適,碌碌庸才,對于文字,僅喜好而已。美食...
  • 我是鐘粽。 03年非典體溫高于36.5被老師責(zé)令回家,公交車喧鬧的前半程竊喜有個別人送的假期,凄涼的后半程害怕自己...
    鐘粽閱讀 110評論 0 0
  • 夫妻本是同林鳥,大難臨頭各自飛,說的就是夫妻,同床異夢,當(dāng)然也泛指夫妻了。 金色的陽光灑滿房間,又是晴朗的一...
    lixueqing閱讀 983評論 0 0

友情鏈接更多精彩內(nèi)容