如何获取数组中的所有唯一对象(具有两个值)?
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; }
我正在将一些坐标存储在一个数组中。它看起来像这样:
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; }