如何获取数组中的所有唯一对象(具有两个值)?

How to get all unique objects (with two values) in an array?

我正在将一些坐标存储在一个数组中。它看起来像这样:

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}]

如何过滤此数组以使对象唯一,这意味着没有重复的对象具有相同的 x 和 y 值?预期输出应为:

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}]

我看过一些类似的解决方案,但都没有真正解决这个问题。 我从以下功能开始

const output = Object.values(
  coords.reduce( (c, e) => {
    if (!c[e.x]) c[e.x] = e;
    return c;
  }, {})

但它只有 returns 个具有不同 x 值的对象,所以它完全忽略了 y 值。

一个想法是使用一个 Set,将 x 和 y 映射到一个字符串中,然后反序列化该 Set 使其具有唯一的 x,y ..

例如..

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}];

const dedup = [...new Set(coords.map(m => `${m.x}:${m.y}`))].map(m => {
  const [x,y] = m.split(':').map(n => n | 0);
  return {x,y};
});

console.log(dedup);

一个非常低效的 (O(n^2)),但灵活且直接的解决方案:您首先定义一个函数来检查两个坐标是否相等。然后过滤所有在数组后面位置具有相等元素的元素。

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}]

const customUnique = (arr, isEqual) => {
  // filter elements where an equal element exists at an earlier position
  // thus the first element is kept
  return arr.filter((a, i) => !arr.some((b, j) => i > j && isEqual(a, b)))
}

console.log(customUnique(coords, (a, b) => a.x === b.x && a.y === b.y))

您可以将 originalArray.reduce() 与数组而不是对象一起使用,因此您可以使用 array.find.

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}]

console.log(
  coords.reduce((arr, e) => {
    if (!arr.find(item => item.x == e.x && item.y == e.y)) {
      arr.push(e);
    }
    return arr;
  }, [])
);

另一个使用临时数组的简单解决方案。然而不是我能说的最好的:

const filteredCoords: any = [];

for(let coord of coords)
  if (!filteredCoords.find((ele: { x: number; y: number; }) => ele.x == coord.x && ele.y == coord.y)){
    filteredCoords.push(coord)
}

我们可以使用Array.reduce(), 连同 Map 以获得所需的结果。

我们将每个项目添加到地图中,使用连接的 x 和 y 值作为键,然后 return values() 以获得去重值。

这将具有 O(n) 的复杂度,因此对于大型数组将是有效的。

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}];

const dedup = [...coords.reduce((map, { x, y }) => {
   return (map.set(`${x}-${y}`, { x, y }));
}, new Map()).values()];

console.log('De-duplicated:', dedup)
     
.as-console-wrapper { max-height: 100% !important; top: 0; }

或使用常规对象:

const coords = [{x: 260, y: 60}, {x: 180, y: 0}, {x: 180, y: 240}, {x: 360, y: 120}, {x: 180, y: 60}, {x: 180, y: 60}, {x: 180, y: 60}];

const dedup = Object.values(coords.reduce((acc, { x, y }) => { 
    return { ...acc, [`${x}-${y}`]: { x, y }}
}, {}));

console.log('De-duplicated:', dedup)
.as-console-wrapper { max-height: 100% !important; top: 0; }