As the various commenters above have pointed out, the answer to your question is largely dependent upon your requirements. If you need to evaluate only on the basis of a single property-- for instance, name
-- it is relatively easy:
let data = [
{ name: "a", position: "A", grade: "" },
{ name: "b", position: "b", grade: "" },
{ name: "c", position: "c", grade: "" },
{ name: "d", position: "d", grade: "" },
{ name: "a", position: "A", grade: "" },
{ name: "e", position: "E", grade: "" },
{ name: "c", position: "c", grade: "" }
]
let arr = [];
data.forEach(datum => {
if (!arr.find(item => item.name === datum.name)) {
arr.push(datum);
}
});
console.log(arr);
In this scenario, you could even conceivably replace the array with a plain object, if that is an acceptable solution. Then you could simply fetch the result with Object.values
. This solution is Set
-like without using an actual Set
, if there is some requirement that prevents it:
let data = [
{ name: "a", position: "A", grade: "" },
{ name: "b", position: "b", grade: "" },
{ name: "c", position: "c", grade: "" },
{ name: "d", position: "d", grade: "" },
{ name: "a", position: "A", grade: "" },
{ name: "e", position: "E", grade: "" },
{ name: "c", position: "c", grade: "" }
]
let dataObject = {};
data.forEach(datum => {
if (!Object.hasOwnProperty(datum.name)) {
dataObject[datum.name] = datum;
}
});
console.log(Object.values(dataObject));
If the evaluation needs to happen simply on the basis of the reference pointing to the same object, it is also relatively easy using Array.prototype.includes
:
let data = [
{ name: "a", position: "A", grade: "" },
{ name: "b", position: "b", grade: "" },
{ name: "c", position: "c", grade: "" },
{ name: "d", position: "d", grade: "" },
{ name: "e", position: "E", grade: "" },
];
let data2 = [
data[1],
data[3],
{ name: "f", position: "F", grade: "" },
data[0],
{ name: "g", position: "G", grade: "" },
]
let arr = [];
function pushData(dataArr) {
dataArr.forEach(datum => {
if (!arr.includes(datum)) {
arr.push(datum);
}
})
}
pushData(data);
pushData(data2);
console.log(arr);
The only place where this begins to become difficult is if you need to check for equivalent objects-- objects with the same property values but that are actually distinct, different objects. If you have a known and relatively simple object shape, you can write your own check for this. For instance, in your case, if you can expect that you will only ever be comparing objects with a name
, position
and grade
property, you could write a custom comparison pretty easily to handle this:
let data = [
{ name: "a", position: "A", grade: "" },
{ name: "b", position: "b", grade: "" },
{ name: "c", position: "c", grade: "" },
{ name: "d", position: "d", grade: "" },
{ name: "a", position: "A", grade: "" },
{ name: "e", position: "E", grade: "" },
{ name: "c", position: "c", grade: "" }
]
let arr = [];
function areDatumsEquivalent(datumA, datumB) {
return (
datumA.name === datumB.name &&
datumA.position === datumB.position &&
datumA.grade === datumB.grade
);
}
data.forEach(datum => {
if(!arr.find(arrDatum => areDatumsEquivalent(datum, arrDatum))) {
arr.push(datum);
}
});
console.log(arr);
However, if it is not the case that you can expect this sort of uniformity from your objects, then you might be better off bringing in a library to do a deep comparison of your objects (such as lodash isEqual
), or looking on Stack Overflow for how people have approached spinning there own solution for deep comparisons:
let data = [
{ name: "a", position: "A", grade: "" },
{ name: "b", position: "b", grade: "" },
{ name: "c", position: "c", grade: "" },
{ name: "d", position: "d", grade: "" },
{ name: "a", position: "A", grade: "" },
{ name: "e", position: "E", grade: "" },
{ name: "c", position: "c", grade: "" }
]
let arr = [];
data.forEach(datum => {
if(!arr.find(arrDatum => _.isEqual(datum, arrDatum))) {
arr.push(datum);
}
});
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Please note that any of the solutions above that leverage nested loops, such as .forEach
and .find
, will scale poorly as the array sizes increase. As such, using Set
or an object/hash based solution might be better from a performance perspective.