文章目錄
- 前言
- 一、使用 `Set` 數據結構
- 二、使用 `filter` + `indexOf`
- 三、使用 `reduce` 累加器
- 四、雙重 `for` 循環
- 五、利用對象屬性唯一性
- 六、先排序后去重
- 七、使用 `Map` 數據結構
- 八、使用 `includes` 方法
- 九、優化處理 `NaN` 的 `filter` 方法
- 十、利用 `findIndex`
- 十一.利用`Set`和展開運算符處理多維數組
- 總結
前言
一、使用 Set
數據結構
function uniqueBySet(arr){return [...new Set(arr)]
}
利用 Set
數據結構中重復元素會被自動過濾的特點。
- 優點:簡單高效,時間復雜度為 O(n)。
- 注意:無法區分對象引用類型,但是可以處理
NaN
。
二、使用 filter
+ indexOf
function uniqueByFilter(arr){return arr.filter((item,index)=> arr.indexOf(item) === index)
}
使用 indexOf
返回元素首次出現的索引,若非當前索引則過濾。
- 注意:時間復雜度為 O(n2),不處理
NaN
,因為indexOf(NaN)
始終返回 -1。
三、使用 reduce
累加器
function uniqueByReduce(arr) {return arr.reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], []);
}
使用 reduce
檢查當前元素是否存在于累加數組中,存在則不添加,不存在則添加。
- 注意:時間復雜度為 O(n2),空間復雜度較高。
四、雙重 for
循環
function uniqueByLoop(arr) {const result = [];for (let i = 0; i < arr.length; i++) {let isDuplicate = false;for (let j = 0; j < result.length; j++) {if (arr[i] === result[j]) {isDuplicate = true;break;}}if (!isDuplicate) result.push(arr[i]);}return result;
}
通過循環嵌套比較元素是否重復。
- 注意:時間復雜度為 O(n2),性能較差。
五、利用對象屬性唯一性
function uniqueByObj(arr){const obj = {}return arr.filter(item=>{const key = typeof item + JSON.stringify(item)return obj.hasOwnProperty(key) ? false :(obj[key] = true) })
對象的鍵名唯一,通過序列化來區分不同類型及對象。
- 注意:
JSON.stringify
無法處理函數、循環引用,性能一般。
六、先排序后去重
function uniqueBySort(arr) {const sortedArr = [...arr].sort();return sortedArr.filter((item, index) => index === 0 || item !== sortedArr[index - 1]);
}
對數組排序后,重復的元素會相鄰,然后直接過濾。
- 注意:原數組順序會被改變。
七、使用 Map
數據結構
function uniqueByMap(arr){const map = new Map()return arr.filter(item=>!map.has(item) && map.set(item,true))
}
利用 Map
鍵的唯一性可以快速判斷元素是否存在。
- 優點:時間復雜度為 O(n),可以正確處理對象引用和
NaN
。
八、使用 includes
方法
function uniqueByIncludes(arr) {const result = [];for (const item of arr) {if (!result.includes(item)) result.push(item);}return result;
}
在遍歷時檢查元素是否已存在于結果數組。
- 注意:時間復雜度為 O(n2),不能處理
NaN
。
九、優化處理 NaN
的 filter
方法
function uniqueWithNaN(arr) {const hasNaN = arr.some(item => Number.isNaN(item));const result = arr.filter((item, index) => {if (Number.isNaN(item)) {// 僅保留第一個NaNreturn !hasNaN || (index === arr.findIndex(i => Number.isNaN(i)));}return arr.indexOf(item) === index;});return result;
}
單獨處理 NaN
,確保只保留第一個出現的 NaN
。
- 優點:該方法兼容
NaN
去重。
十、利用 findIndex
function uniqueByFindIndex(arr) {return arr.filter((item, index) => {return arr.findIndex(i => i === item) === index;});
}
使用 findIndex
和 indexOf
方法類似,但是可以處理自定義處理 NaN
。
十一.利用Set
和展開運算符處理多維數組
function uniqueMultidimensionalArray(arr) {return Array.from(new Set(arr.flat(Infinity)));
}
首先利用flat
方法將多維數組扁平化,然后利用Set
去除重復元素,最后通過Array.from
將Set
轉換會數組
- 注意:該方法只能處理元素為基本類型或可序列化的對象的多維數組。如果數組中包含函數,循環引用等特殊對象,
flat
方法和Set
可能無法正確處理
總結
- 簡單場景:優先使用
Set
或Map
,簡潔高效。 - 兼容性要求:使用
filter + indexOf
或者雙重循環。 - 含
NaN
或者對象:選擇Map
或改進的對象屬性方法。 - 排序無影響:排序后去重效率高 。