I found this example on
https://blog.adriaan.io/make-array-with-objects-unique-on-multiple-keys-in-javascript.html
const browsers = [
{ os: "OS X",
os_version: "Catalina",
browser: "chrome",
browser_version: "30.0"
},
{
os: "Windows",
os_version: "7",
browser: "chrome",
browser_version: "40.0"
},
{
os: "Windows",
os_version: "7",
browser: "chrome",
browser_version: "50.0"
}
];
const makeUnique = (array = [], keys = []) => {
if (!keys.length || !array.length) return [];
return array.reduce((list, item) => {
const hasItem = list.find(listItem => keys.every(key => listItem[key] === item[key]) );
if (!hasItem) list.push(item);
return list;
},[]);
};
console.log(makeUnique(browsers, ["os", "os_version"]));
I would like to use this with my objectarray but i use keys in a key. Does anyone know how to adapt the method to my example in order to ignore double bounds?
const tiles = [
{
name: "pattern1",
type: "jpg",
size: 1024,
bounds:{topleft_x: 45, topleft_y: 45, downright_x: -45, downright_y: -45},
},
name: "pattern2",
type: "jpg",
size: 1024,
bounds:{topleft_x: 90, topleft_y: 90, downright_x: 45, downright_y: 45},
},
name: "pattern3",
type: "jpg",
size: 1024,
bounds:{topleft_x: 45, topleft_y: 45, downright_x: -45, downright_y: -45},
},
//...
];
CodePudding user response:
you need a traverse function this function gets an object and a string called path, path is something like bounds.topleft_y
function traverse(obj, path) {
if (!path.includes('.')) return obj[path];
return path.split('.').reduce((a, k) => a[k], obj)
}
and you need to change makeUnique function
const makeUnique = (array = [], keys = []) => {
if (!keys.length || !array.length) return [];
return array.reduce((list, item) => {
const hasItem = list.find(listItem => keys.every(key => traverse(listItem, key) === traverse(item, key)));
console.log(data, item, hasItem)
if (!hasItem) list.push(item);
return list;
}, [])
}
and here is how you can use it
makeUnique(data, ['type', 'bounds.topleft_y'])
CodePudding user response:
The crux of any deduping algorithm is how equality is determined. In the example algorithm you provided, that occurs with checking listItem[key] === item[key]
. Strict equality (===) works great for comparing primitive values, but there is no built-in way to compare objects (like bounds
). Therefore, you have to use a custom value equality function.
There is a great npm package called value-equal
that does this for you. You can also view its implementation here.
Once you have a valueEqual()
function, you can swap it into the algorithm like so:
const makeUnique = (array = [], keys = []) => {
if (!keys.length || !array.length) return [];
return array.reduce((list, item) => {
const hasItem = list.find(listItem => keys.every(key => valueEqual(listItem[key], item[key])));
if (!hasItem) list.push(item);
return list;
},[]);
};
Then you can invoke the algorithm as before:
console.log(makeUnique(tiles, ["type", "bounds"]));