使用?filter
?和?Map
?根據鍵值去重
我來詳細解釋方法2,這是一種高效且簡潔的數組去重方法,特別適合根據對象中的某個鍵值進行去重操作。
完整代碼
function uniqueByKey(arr, key) {return [...new Map(arr.map(item => [item[key], item])).values()];
}
分步解析
讓我們分解這個方法的每個步驟:
arr.map(item => [item[key], item])
遍歷原始數組,為每個元素創建一個新數組
新數組的第一個元素是對象的鍵值(
item[key]
)第二個元素是對象本身(
item
)例如,對于?
{id: 1, name: 'John'}
,當 key 是 'id' 時,會變成?[1, {id: 1, name: 'John'}]
new Map()
將上一步生成的數組對傳遞給?
Map
?構造函數Map
?對象會自動處理鍵值對,當有相同的鍵時,后面的值會覆蓋前面的值這是去重的關鍵步驟,因為?
Map
?的鍵必須是唯一的
.values()
獲取?
Map
?中所有的值(即原始對象)這會返回一個?
MapIterator
?對象
[... ]
使用擴展運算符將?
MapIterator
?轉換為普通數組
為什么這個方法有效?
Map
?對象的特點是鍵必須是唯一的當我們把對象的鍵值作為?
Map
?的鍵,對象本身作為值時:如果遇到相同的鍵值,后面的對象會覆蓋前面的對象
最終?
Map
?中只保留每個鍵值的最后一個對象
通過?
values()
?方法,我們只獲取對象部分,忽略鍵
示例演示
假設我們有如下數組:
const data = [{id: 1, name: 'John'},{id: 2, name: 'Jane'},{id: 1, name: 'Johnny'}, // 重復的 id:1{id: 3, name: 'Alice'}
];
執行步驟:
data.map(item => [item['id'], item])
?生成:[[1, {id: 1, name: 'John'}],[2, {id: 2, name: 'Jane'}],[1, {id: 1, name: 'Johnny'}],[3, {id: 3, name: 'Alice'}] ]
new Map()
?處理后:Map {1 => {id: 1, name: 'Johnny'}, // 后面的覆蓋了前面的2 => {id: 2, name: 'Jane'},3 => {id: 3, name: 'Alice'} }
.values()
?獲取:MapIterator {{id: 1, name: 'Johnny'},{id: 2, name: 'Jane'},{id: 3, name: 'Alice'} }
[... ]
?轉換為數組:[{id: 1, name: 'Johnny'},{id: 2, name: 'Jane'},{id: 3, name: 'Alice'} ]
注意事項
保留最后一個重復項:這個方法會保留最后一個遇到的重復鍵值對象,而不是第一個
性能優勢:對于大型數組,這種方法通常比其他方法(如使用?
filter
?+?find
)性能更好,因為?Map
?的查找操作是 O(1) 復雜度鍵值類型:鍵值可以是任何類型,但會被?
Map
?轉換為字符串形式進行比較
如果需要保留第一個遇到的重復項而不是最后一個,可以先將數組反轉,處理后再反轉回來:
function uniqueByKeyKeepFirst(arr, key) {return [...new Map([...arr].reverse().map(item => [item[key], item])).values()].reverse();
}