JS數(shù)組去重詳情
1 測(cè)試用例
// 測(cè)試用例 const a = {}; const b = { c: 1 }; const array = [ 1, 1, "1", "1", {}, {}, { c: 1 }, { c: 1}, a, a, b, b, [], [], [1], [1], undefined, undefined, null, null, NaN, NaN, ];
2 JS 數(shù)組去重4大類型
2.1 元素比較型
此類型通過數(shù)組元素之間進(jìn)行比較來去重
2.1.1 雙層 for 循環(huán)逐一比較(es5常用)
使用雙層for循環(huán)逐一比較數(shù)組元素,用splice
方法去除重復(fù)的元素
// 雙層for循環(huán) function uniq1(arr) { 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) j-- } } } return arr } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]
通過對(duì)比去重前后結(jié)果,重復(fù)的NaN
沒有去掉,因?yàn)?code>NaN === NaN為false
2.1.2 排序相鄰比較
使用sort()
方法對(duì)數(shù)組元素進(jìn)行排序,然后比較相鄰元素,用splice
方法去除重復(fù)的元素。
function uni2(arr) { arr.sort(); for (let i = 0; i < arr.length - 1; i++) { arr[i] === arr[i + 1] && arr.splice(i + 1, 1) && i--; } return arr; }
也可以創(chuàng)建新數(shù)組,將不重復(fù)的元素放入新數(shù)組中
function uniq3(arr) { arr = arr.sort() const newArr = [arr[0]] for (let i = 1; i < arr.length; i++) { if (arr[i] !== arr[i - 1]) { newArr.push(arr[i]) } } return newArr } // 去重結(jié)果 // [[],[],1,'1',[1],[1],NaN,NaN,{},{},{c:1},{c:1},{},{c:1},null,undefined]
重復(fù)的NaN
沒有去掉,因?yàn)?code>NaN === NaN為false
sort默認(rèn)排序順序是將元素轉(zhuǎn)換為字符串,對(duì)象轉(zhuǎn)換為字符串都是[object Object]
,所以sort
方法不能對(duì)數(shù)組中的對(duì)象進(jìn)行排序,也就有可能無法去除重復(fù)的對(duì)象,除非重復(fù)的對(duì)象本就相鄰
2.2 查找元素位置型
此類型通過查找元素第一次出現(xiàn)的位置來去重
2.2.1 indexOf
通過indexOf
查找當(dāng)前元素第一次出現(xiàn)的位置是否為當(dāng)前位置,若是,則放入新數(shù)組
function uniq4(arr) { let res = [] for (let i = 0; i < arr.length; i++) { if (arr.indexOf(arr[i]) === i) { res.push(arr[i]) } } return res } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]
同樣,因?yàn)?code>NaN === NaN為false
,所以用indexOf
查找NaN
結(jié)果總是-1,從而在新數(shù)組中不會(huì)有NaN
2.2.2 findIndex
通過findIndex
查找當(dāng)前元素第一次出現(xiàn)的位置是否為當(dāng)前位置,若是,則放入新數(shù)組
function uniq5(arr) { let res = [] for (let i = 0; i < arr.length; i++) { if (arr.findIndex(item => item === arr[i]) === i) { res.push(arr[i]) } } return res } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]
同樣,因?yàn)?code>NaN === NaN為false
,所以用findIndex
查找NaN
結(jié)果總是-1,從而在新數(shù)組中不會(huì)有NaN
2.3 元素是否存在型
此類型通過判斷在新數(shù)組中是否存在當(dāng)前元素來去重
2.3.1 includes
includes
方法用來判斷一個(gè)數(shù)組是否包含一個(gè)指定的值
function uniq6(arr) { let res = [] for (let i = 0; i < arr.length; i++) { if (!res.includes(arr[i])) { res.push(arr[i]) } } return res } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
includes
使用零值相等算法來確定是否找到給定的元素,所以可以判斷NaN是否在新數(shù)組中存在
2.3.2 some
some
方法用來測(cè)試數(shù)組中是否至少有1個(gè)元素通過了被提供的函數(shù)測(cè)試
function uniq7(arr) { let res = [] for (let i = 0; i < arr.length; i++) { if (!res.some(item => item === arr[i])) { res.push(arr[i]) } } return res } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]
同樣,這里仍舊使用了===
來比較元素,因?yàn)?code>NaN === NaN為false
,所以新數(shù)組中會(huì)有多個(gè)NaN
2.4 依托數(shù)據(jù)結(jié)構(gòu)特性
此類型通過ES6提供的數(shù)據(jù)結(jié)構(gòu)Map
、Set
本身不可重復(fù)特性來去重
2.4.1 Map
ES6
提供的Map結(jié)構(gòu)可以用各種類型的值(包括對(duì)象)當(dāng)作鍵,且鍵是唯一的
function uniq8(arr) { const map = new Map() for (let i = 0; i < arr.length; i++) { !map.has(arr[i]) && map.set(arr[i], true) } return [...map.keys()] } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
map.has
方法對(duì)NaN
也有效
2.4.2 Set(ES6 最常用)
Set
結(jié)構(gòu)的成員的值都是唯一的,沒有重復(fù)的值。
function uniq9(arr) { return [...new Set(arr)] } // 去重結(jié)果 // [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
3 補(bǔ)充
上面所說的方法可以使用不同的Api
進(jìn)行改動(dòng),比如使用splice
方法去除數(shù)組元素的地方,我們可以通過filter
方法來過濾數(shù)組得到新數(shù)組;
再比如includes
的方法中不用for
循環(huán)遍歷數(shù)組,通過reduce
方法來代替等等。
總之,方法有很多,但是萬變不離其宗
有些去重方法對(duì)NaN
無效,因?yàn)?code>NaN === NaN為false
,如果有需求,可以使用Object.is(NaN, NaN)
為true
來進(jìn)行修改
實(shí)際應(yīng)用中,最常用的方法就是使用Set,也可以使用第三方庫lodash
來處理
到此這篇關(guān)于JS數(shù)組去重詳情的文章就介紹到這了,更多相關(guān)JS數(shù)組去重內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
類和原型的設(shè)計(jì)模式之復(fù)制與委托差異
這篇文章主要為大家介紹了類和原型的設(shè)計(jì)模式之復(fù)制與委托差異詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07微信小程序 小程序制作及動(dòng)畫(animation樣式)詳解
這篇文章主要介紹了微信小程序 小程序制作及動(dòng)畫詳解的相關(guān)資料,這里對(duì)小程序制作進(jìn)行了詳解,介紹動(dòng)畫部分的知識(shí),需要的朋友可以參考下2017-01-01微信小程序 自動(dòng)登陸PHP源碼實(shí)例(源碼下載)
這篇文章主要介紹了微信小程序 自動(dòng)登陸PHP源碼實(shí)例并且附有源碼的相關(guān)資料,需要的朋友可以參考下2017-05-05跨端開發(fā)框架avm組件封裝經(jīng)驗(yàn)分享
這篇文章主要為大家介紹了跨端開發(fā)框架avm組件封裝的經(jīng)驗(yàn)分享,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07前端對(duì)接WebSocket與心跳重連實(shí)現(xiàn)
這篇文章主要為大家介紹了前端對(duì)接WebSocket與心跳重連實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07采用CSS和JS,剛好我最近有個(gè)站點(diǎn)要用到下拉菜單!
采用CSS和JS,剛好我最近有個(gè)站點(diǎn)要用到下拉菜單!...2006-06-06