1 測試用例
// 測試用例
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ù)組元素之間進行比較來去重
2.1.1 雙層 for 循環(huán)逐一比較(es5常用)
使用雙層for
循環(huán)逐一比較數(shù)組元素,用splice
方法去除重復的元素
// 雙層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
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]
通過對比去重前后結果具伍,重復的NaN
沒有去掉嫂侍,因為NaN === NaN
為false
2.1.2 排序相鄰比較
使用sort()
方法對數(shù)組元素進行排序凛篙,然后比較相鄰元素依许,用splice
方法去除重復的元素申尼。
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ù)組寂曹,將不重復的元素放入新數(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
}
// 去重結果
// [[],[],1,'1',[1],[1],NaN,NaN,{},{},{c:1},{c:1},{},{c:1},null,undefined]
- 重復的
NaN
沒有去掉感憾,因為NaN === NaN
為false
-
sort
默認排序順序是將元素轉換為字符串,對象轉換為字符串都是[object Object]
境钟,所以sort
方法不能對數(shù)組中的對象進行排序锦担,也就有可能無法去除重復的對象,除非重復的對象本就相鄰
2.2 查找元素位置型
此類型通過查找元素第一次出現(xiàn)的位置來去重
2.2.1 indexOf
通過indexOf
查找當前元素第一次出現(xiàn)的位置是否為當前位置慨削,若是洞渔,則放入新數(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
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]
同樣套媚,因為NaN === NaN
為false
,所以用indexOf
查找NaN
結果總是-1
磁椒,從而在新數(shù)組中不會有NaN
2.2.2 findIndex
通過findIndex
查找當前元素第一次出現(xiàn)的位置是否為當前位置堤瘤,若是,則放入新數(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
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null]
同樣衷快,因為NaN === NaN
為false
宙橱,所以用findIndex
查找NaN
結果總是-1
,從而在新數(shù)組中不會有NaN
2.3 元素是否存在型
此類型通過判斷在新數(shù)組中是否存在當前元素來去重
2.3.1 includes
includes
方法用來判斷一個數(shù)組是否包含一個指定的值
function uniq6(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
if (!res.includes(arr[i])) {
res.push(arr[i])
}
}
return res
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
includes
使用零值相等算法來確定是否找到給定的元素蘸拔,所以可以判斷NaN
是否在新數(shù)組中存在
2.3.2 some
some
方法用來測試數(shù)組中是否至少有1個元素通過了被提供的函數(shù)測試
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
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN,NaN]
同樣师郑,這里仍舊使用了===
來比較元素,因為NaN === NaN
為false
调窍,所以新數(shù)組中會有多個NaN
2.4 依托數(shù)據(jù)結構特性
此類型通過ES6
提供的數(shù)據(jù)結構Map
宝冕、Set
本身不可重復特性來去重
2.4.1 Map
ES6
提供的Map
結構可以用各種類型的值(包括對象)當作鍵,且鍵是唯一的
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()]
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
map.has
方法對NaN
也有效
2.4.2 Set(ES6 最常用)
Set
結構的成員的值都是唯一的邓萨,沒有重復的值地梨。
function uniq9(arr) {
return [...new Set(arr)]
}
// 去重結果
// [1,'1',{},{},{c:1},{c:1},{},{c:1},[],[],[1],[1],undefined,null,NaN]
3 補充
-
上面所說的方法可以使用不同的
Api
進行改動,比如使用splice
方法去除數(shù)組元素的地方缔恳,我們可以通過filter
方法來過濾數(shù)組得到新數(shù)組宝剖;再比如
includes
的方法中不用for
循環(huán)遍歷數(shù)組,通過reduce
方法來代替等等歉甚。總之万细,方法有很多,但是萬變不離其宗
有些去重方法對
NaN
無效纸泄,因為NaN === NaN
為false
赖钞,如果有需求,可以使用Object.is(NaN, NaN)
為true
來進行修改實際應用中聘裁,最常用的方法就是使用
Set
雪营,也可以使用第三方庫lodash
來處理