ES6 set和map数据结构对对象数组去重简单实现
自从有了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并不相等,当然就起不到去重的效果。如果有更正确和深入的理解欢迎讨论哈