這個問題在這里已經有了答案: 如何根據 2 個屬性洗掉陣列中的重復物件? (6 個回答) 7 小時前關閉。
我將一些坐標存盤在一個陣列中。它看起來像這樣:
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;
}, {})
但它只回傳具有不同 x 值的物件,所以它完全忽略了 y 值。
uj5u.com熱心網友回復:
一種想法是使用 Set,將 x & y 映射到字串中,然后將 Set 反序列化以獲得唯一的 x,y's..
例如..
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);
uj5u.com熱心網友回復:
我們可以使用Array.reduce()和Map來獲得所需的結果。
我們將每個專案添加到地圖中,使用連接的 x 和 y 值作為鍵,然后回傳 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; }
uj5u.com熱心網友回復:
一個非常低效的 (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))
uj5u.com熱心網友回復:
您可以使用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;
}, [])
);
uj5u.com熱心網友回復:
另一個使用臨時陣列的簡單解決方案。然而,不是我能說的最好的:
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)
}
uj5u.com熱心網友回復:
.sort輸入首先由 x 然后由 y。這會將重復的專案放在一起。然后.reduce排序陣列保留唯一項(此步驟只需要一次傳遞):
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 sorted = coords.slice(); // don't sort the original array
sorted.sort((a, b) => a.x - b.x || a.y - b.y);
const output = sorted.reduce((arr, val) => {
if (arr.length === 0 || arr[arr.length - 1].x !== val.x || arr[arr.length - 1].y !== val.y) {
arr.push(val);
}
return arr;
}, []);
console.log(output);
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/376767.html
上一篇:在主串列中搜索聚合結果
