添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
英勇无比的仙人掌  ·  How To Fix The Error ...·  3 小时前    · 
酷酷的领带  ·  Encountering error ...·  3 小时前    · 
冷静的勺子  ·  中间件 | Docs·  17 小时前    · 
玩命的草稿本  ·  测试 | Vuex·  2 天前    · 
爱搭讪的凉面  ·  南方周末·  4 月前    · 

获取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' } ]