自從有了es6的set數據結構,數組的去重可以簡單用一行代碼實現,比如下面的方式
let arr = [1, 2, 2, 3, 4] function unique (arr) { return [...new Set(arr)] } console.log(unique(arr)) // [1, 2, 3, 4]
但是當數組的項不再是簡單的數據類型時,比如是對象時,這種方法就會導致錯誤,比如下面的結果
let arr = [ { name: 'a', num: 1}, { name: 'b', num: 1}, { name: 'c', num: 1}, { name: 'd', num: 1}, { name: 'a', num: 1}, { name: 'a', num: 1}, { name: 'a', num: 1} ] function unique (arr) { return [...new Set(arr)] } console.log(unique(arr)) // 結果為原數組,有興趣可以復制代碼試一下
其中的原因是因為set數據結構認為對象永不相等,即使是兩個空對象,在set結構內部也是不等的
基於以上原因,利用map和set結構封裝了一種對對象數組去重的簡單方法,其實他們本質都是一樣的,只是使用sjon.stringfy()和json.parse()會影響性能,具體如下
// ES6對象數組所有屬性去重,篩選每個數組項的字符 function unique(arr) { const map = new Map() return arr.filter( item => !map.has(JSON.stringify(item)) && map.set(JSON.stringify(item), 1)) }
function unique(arr) {
return [...new Set(arr.map(e => JSON.stringify(e)))].map(e => JSON.parse(e))
}
// ES6根據一維對象數組某個屬性去重且該屬性的值為簡單數據類型,比較實用的一種的方法,也基本沒有什么性能影響 function unique(arr, key) { const map = new Map() return arr.filter((item) => !map.has(item[key] + '') && map.set(item[key] + '', 1)) }
網上有朋友設計了一種更簡單的方法,主要是對map數據結構的鍵理解得不一樣,其他沒什么區別,代碼如下
// ES6對象數組所有屬性去重,篩選每個數組項的字符 function unique2(arr) { const map = new Map() return arr.filter( item => !map.has(item) && map.set(item, 1)) }
實際試了一下,發現沒有起到去重的效果,不知道具體原因是什么,我的理解是當用item指代數組中的每一項的對象的時候,item保存的是對對象的指針,即棧中的地址,並不是對象本身,所以每一個item的地址是不一樣的,盡管他們都指向同一個堆數據,所以map認為每一個item並不相等,當然就起不到去重的效果。如果有更正確和深入的理解歡迎討論哈
