数组去重
数组去重是日常编码中很常用的算法。
Set实现
Set
对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
const arr = [1, 2, 3, 1, 3];
[...new Set(arr)]
// [1, 2, 3]
但实际开发中,很少能对引用类型直接使用 [...new Set(list)]
去重,因为需要引用指向同一个对象,仅字面量相同是不行的。
例如:
const a = {name: 'a'};
const b = {name: 'a'};
const c = a;
[...new Set([a, b])]
// [{name: 'a'}, {name: 'a'}]
[... new Set([a, c])]
// [{name: 'a'}]
偏移量实现
针对引用类型,一般的实现思路是通过找到引用的唯一值,如id
、key
等,判断是否是第一次出现,如果是第二次出现,则表示重复了。
const arr = [{id: 1}, {id: 2}, {id: 1}];
arr.filter((x, i, xs) => {
// 如果是第一次出现,findIndex返回的值应该与i相等
return xs.findIndex(item => item.id === x.id) === i;
});
// [{id: 1}, {id: 2}]
以上代码在循环中还有循环,时间复杂度为O(n2),我们还可以利用Object缓存已经出现过的项,近一步优化。
最终代码
/**
* @param { Array } arr 数组
* @param { String | undefined } property 唯一值的属性,如id、key等
*/
function unique(arr = [], property) {
if (!property) {
return [... new Set(arr)]
}
const record = {};
const result = [];
for (let crt of arr) {
const val = crt[property];
if (record[val]) {
continue;
}
record[val] = true;
result.push(crt);
}
return result;
}