获取JavaScript数组中的所有唯一值并删除重复项
在JavaScript中从数组中删除重复项可以通过多种方式实现,例如使用Array.prototype.reduce()
、Array.prototype.filter()
甚至是简单的for
循环。但是,有一种更简单的方法,使用内置的Set
对象。
获取数组中的所有唯一值
Set
不能包含重复值,并且可以很容易地从数组的值初始化。然后,由于它本身是可迭代的,我们可以使用扩展运算符(...
)将其转换回仅包含唯一值的数组。
const uniqueElements = arr => [...new Set(arr)];
uniqueElements([1, 2, 2, 3, 4, 4, 5]); // [1, 2, 3, 4, 5]
检查数组是否包含重复项
Set
没有length
属性,但它有一个size
属性。我们可以使用这个属性来检查数组是否包含重复项。
const hasDuplicates = arr => arr.length !== new Set(arr).size;
hasDuplicates([1, 2, 2, 3, 4, 4, 5]); // true
hasDuplicates([1, 2, 3, 4, 5]); // false
反转条件,我们可以检查数组的所有值是否都是不同的。
const allDistinct = arr => arr.length === new Set(arr).size;
allDistinct([1, 2, 2, 3, 4, 4, 5]); // false
allDistinct([1, 2, 3, 4, 5]); // true
删除出现多次的数组值
如果我们只想保留不重复的值,可以使用Array.prototype.filter()
方法。出现多次的元素必须在至少两个不同的索引中出现,因此我们可以使用Array.prototype.indexOf()
和Array.prototype.lastIndexOf()
来检查。如果我们预计数组中有许多重复的值,先将其转换为Set
可能会提高性能。
const removeNonUnique = arr =>
[...new Set(arr)].filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
removeNonUnique([1, 2, 2, 3, 4, 4, 5]); // [1, 3, 5]
我们也可以做相反的操作,删除只出现一次的所有值。在这种情况下,两个索引必须相同。请注意,对于这个操作使用Set
将从结果中删除重复项。
const removeUnique = arr =>
[...new Set(arr)].filter(i => arr.indexOf(i) !== arr.lastIndexOf(i));
removeUnique([1, 2, 2, 3, 4, 4, 5]); // [2, 4]
使用函数查找重复项
更复杂的数据,例如对象,无法使用相等比较进行比较,因此我们需要使用一个函数来检查重复项。在这里,Set
对象没有太大用处,所以我们可以使用Array.prototype.reduce()
和Array.prototype.some()
手动将唯一值填充到一个新数组中。使用数组方法,我们还可以检查数组是否包含重复项,或者删除出现多次的所有值。
const uniqueElementsBy = (arr, fn) =>
arr.reduce((acc, v) => {
if (!acc.some(x => fn(v, x))) acc.push(v);
return acc;
}, []);
const hasDuplicatesBy = (arr, fn) =>
arr.length !== new Set(arr.map(fn)).size;
const removeNonUniqueBy = (arr, fn) =>
arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));
const data = [
{ id: 0, value: 'a' },
{ id: 1, value: 'b' },
{ id: 2, value: 'c' },
{ id: 1, value: 'd' },
{ id: 0, value: 'e' }
];
const idComparator = (a, b) => a.id == b.id;
const idMap = a => a.id;
uniqueElementsBy(data, idComparator);
// [ { id: 0, value: 'a' }, { id: 1, value: 'b' }, { id: 2, value: 'c' } ]
hasDuplicatesBy(data, idMap); // true
removeNonUniqueBy(data, idComparator); // [ { id: 2, value: 'c' } ]