當前位置:
首頁 > 知識 > js數組去重方法分析與總結

js數組去重方法分析與總結


數組去重經常被人拿來說事,雖然在工作中不常用,但他能夠很好的考察js基礎知識掌握的深度和廣度,下面從js的不同階段總結一下去重的方法。

ES3階段

該階段主要通過循環遍曆數組從而達到去重的目的

  • 多次循環去掉重複元素

// 以下所有方法默認都那拿該數組進行測試
var array = [1, 1, "1", "1", null, null, undefined, undefined, new String("1"), new String("1"), /a/, /a/, NaN, NaN,{},{},[],,{name: "eric",sex: "male"},{sex: "male",name: "eric"}];
function unique_es3_on2 (arr) {
var len = arr.length,
i = 0,
j,
flag,
ret = ;
for (; i < len ; i++) {
flag = true;
for (j = i+1 ; j < len ; j++) {
if (arr[i] === arr[j]) {
flag = false;
break;
}
}
if(flag) {
ret.push(arr[i]);
}
}
return ret;
}
unique_es3_on2(array)

結果如下圖:

js數組去重方法分析與總結

可見除了NaN沒有去掉,其他效果都還挺好。原因就是NaN===NaN的結果是false。還有就是使用嵌套的循環,時間複雜度高,性能不是很好。

  • 藉助新的對象單次循環去掉重複元素

function unique_es3_on(arr) {
var obj = {},
i,
len = arr.length,
ret = ;
for(i = 0; i < len ; i++) {
if(!obj[arr[i]]) {
obj[arr[i]] = true;
ret.push(arr[i]);
}
}
return ret;
}

結果如下圖:

js數組去重方法分析與總結

雖然時間複雜度不高了,但是效果並不好。因為對象的屬性是字元串,所以會把數組所有元素默認轉化為字元串,就會產生以下問題:

  1. 數值1和字元串"1"以及包裝類型new String("1"),轉化為字元串以後是相同的會被去掉。
  2. 對象轉化為字元串以後會被誤判,==>"",{}==>"[object Object]",還有就是形式相同,內存地址不同的對象會被去除。

為了解決類型轉換以後出現的問題,可以用typeof操作符轉一下:

function unique_es3_on(arr) {
var obj = {},
i,
len = arr.length,
str,
ret = ;
for(i = 0; i < len ; i++) {
str = typeof arr[i] + arr[i];
if(!obj[str]) {
obj[str] = true;
ret.push(arr[i]);
}
}
return ret;
}

結果如圖:

js數組去重方法分析與總結

可以看到類型轉換的問題基本解決,但對象部分基本都被去除了,因為他們和字元串相加時還是會發生轉化,解決的方案是把上面的str換成str = typeof arr[i] + JSON.stringify(arr[i]),相加之前先簡單序列化一下。

結果如圖:

js數組去重方法分析與總結


從以上可以看出該階段的各種方法或多或少的都有一些問題,該去除的沒去掉,比如NaN。不該去的給去掉了,比如,形式相同但內存地址不同的對象(是否應該去掉全看你怎麼定義)。

ES5階段

function unique_es5(arr) {
return arr.filter(function(ele,index,array) {
return array.indexOf(ele) == index;
})
}

結果如圖:

js數組去重方法分析與總結

可以看到除了NaN,其他表現都是正常的。其中indexOf對於NaN總是返回-1,所以導致誤判。

ES6階段

let unique_includes = (arr) => {
let newArr = ;
arr.forEach(function(item){
if(!newArr.includes(item)){
newArr.push(item);
}
});
return newArr;
}

結果如圖:

js數組去重方法分析與總結

可以看到結果是符合預期的,es6中數組的擴展方法includes解決了用indexOf的弊端(不夠直觀,結果還要和索引進行比較。對NaN的誤判)。

let unique_set = (arr) => {
return [...new Set(arr)];
}

結果和includes方法一樣,此處利用es6新增數據結構set的特性,達到去重的目的。

let unique_map = (arr) => {
let ret = ,
m = new Map;
for(val of arr) {
if(!m.get(val)) {
m.set(val , true);
ret.push(val);
}
}
return ret;
}

結果和includes一樣:

此處利用es6新增數據結構map的特性,之前的鍵值對集合(js對象),只能用字元串當作健,map這種數據結構打破了這一限制,各種類型的值都可以當作健,而且map的健是跟內存地址綁定的,只要內存地址不同就認為是不同的健,解決了之前形式相同而內存地址不同被去掉的問題。對於簡單數據類型,只要嚴格相等就認為是相同的健,特例NaN也認為是相同的健。所以就解決了之前的兩個大難題。

總結

雖然只是一個簡單的去重問題,但這一路實踐下來,可以看到js越來越強大,功能也越來越完善,同時也越來越優雅。現在再聽到有人說,js只是處理簡單表單驗證的玩具車語言之類的云云,我想我也會忍不住在他耳邊懟一句:那他媽是從前。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

mysql中varchar和char區別
隨筆-64 文章-0 評論-26
HttpClient筆記與踩過的坑

TAG:科技優家 |

您可能感興趣

最全的JS數組去重
帥爆了! 南宮珉自掏腰包帶《Dr. Prisoner》劇組去夏威夷旅行
COD15被曝原本有單人戰役:T組去年中旬將其砍掉
來一場六發左輪的爐石對決!帶上這些卡組去大殺四方吧!
慈寧宮不開放的秘密:88年一個劇組去故宮取景,為何落荒而逃?
30年前,一劇組去故宮取景拍戲,大半夜落荒而逃,究竟發生了什麼?
30年前,一劇組去故宮拍戲,大半夜落荒而逃,到底發生了什麼?
搞笑裝逼三人組去殺紅髮,幾點說明這超新星比路飛實力更強!
小公爺和明蘭在這座江南小城都吃了啥?趁人少,趕緊跟著《知否》劇組去打卡!