How to remove all duplicates from an array of objects?
How about with some es6
magic?
things.thing = things.thing.filter((thing, index, self) => index === self.findIndex((t) => ( t.place === thing.place && t.name === thing.name )))
A more generic solution would be:
const uniqueArray = things.thing.filter((thing, index) => { const _thing = JSON.stringify(thing); return index === things.thing.findIndex(obj => { return JSON.stringify(obj) === _thing; });});
Using the above property strategy instead of JSON.stringify
:
const isPropValuesEqual = (subject, target, propNames) => propNames.every(propName => subject[propName] === target[propName]);const getUniqueItemsByProperties = (items, propNames) => items.filter((item, index, array) => index === array.findIndex(foundItem => isPropValuesEqual(foundItem, item, propNames)) );
You can add a wrapper if you want the propNames
property to be either an array or a value:
const getUniqueItemsByProperties = (items, propNames) => { const propNamesArray = Array.from(propNames); return items.filter((item, index, array) => index === array.findIndex(foundItem => isPropValuesEqual(foundItem, item, propNamesArray)) );};
allowing both getUniqueItemsByProperties('a')
and getUniqueItemsByProperties(['a']);
Explanation
- Start by understanding the two methods used:
- Next take your idea of what makes your two objects equal and keep that in mind.
- We can detect something as a duplicate, if it satisfies the criterion that we have just thought of, but it's position is not at the first instance of an object with the criterion.
- Therefore we can use the above criterion to determine if something is a duplicate.
Shortest one liners for ES6+
Find unique id
's in an array.
arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i)
Unique by multiple properties ( place
and name
)
arr.filter((v,i,a)=>a.findIndex(t=>(t.place === v.place && t.name===v.name))===i)
Unique by all properties (This will be slow for large arrays)
arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)
Keep the last occurrence.
arr.slice().reverse().filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i).reverse()
A primitive method would be:
var obj = {};for ( var i=0, len=things.thing.length; i < len; i++ ) obj[things.thing[i]['place']] = things.thing[i];things.thing = new Array();for ( var key in obj ) things.thing.push(obj[key]);