Check if array of objects includes an object

Viewed 139

I am trying to check if an array of objects includes a object. I want it to return true when there is a object in the array that has the same values and the object id should not matter. This is how i thought it would work:

let arr = [{r:0, g:1}];
let obj = {r:0, g:1}

console.log(arr.includes(obj));

But it returns false and I need it to return true. Do I have to convert every object in the array to a string with JSON.stringify() and the object I am searching for like this:

let arr = [JSON.stringify({r: 0, g: 1})]
let obj = {r: 0, g: 1}

console.log(arr.includes(JSON.stringify(obj)));

Is there another easier and more efficient way to do it with more objects?

4 Answers

You get false because objects are compared by a reference to the object, while you got there 2 separate object instances.

Wile JSON.stringify might work, keep in mind that the order of properties is not guaranteed and it may fail if the order is not the same, because you get a different string.

you can check for an id property or compare several properties to match against, if you must you can compare all properties with a loop.

If you have an access to the object's reference, you can use a Map or a Set which allows you to store and check references

const obj = {r:0, g:1};
const obj2 = {r:0, g:1};
const mySet = new Set();
// given the fact that you do have access to the object ref
mySet.add(obj);

const isObjInList = mySet.has(obj);
const isObj2InList = mySet.has(obj2);

console.log('is obj in list - ', isObjInList);
console.log('is obj2 in list - ', isObj2InList);

I like to use Set() for this purposes, read from the documentation:

The Set object lets you store unique values of any type, whether primitive values or object references.

See the below example:

let obj = {r:0, g:1};
const set = new Set();
set.add(obj);

console.log(set.has(obj));

I hope that helps!

You can use the JavaScript some() method to find out if a JavaScript array contains an object.

This method tests whether at least one element in the array passes the test implemented by the provided function. Here's an example that demonstrates how it works:

 // An array of objects
    var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];

    // Find if the array contains an object by comparing the property value
    if(persons.some(person => person.name === "Peter")){
        alert("Object found inside the array.");
    } else{
        alert("Object not found.");
    }

Note that if try to find the object inside an array using the indexOf() method like persons.indexOf({name: "Harry"}) it will not work (always return -1). Because, two distinct objects are not equal even if they look the same (i.e. have the same properties and values). Likewise, two distinct arrays are not equal even if they have the same values in the same order.

The some() method is supported in all major browsers, such as Chrome, Firefox, IE (9 and above), etc. See the tutorial on JavaScript ES6 Features to learn more about arrow function notation.

JSON.stringify doesn't work as expected if you change the order of properties in one of the objects.

You can use .some in combination with isEqual from lodash (or other alternatives). Or you can write it by yourself, but be careful, there are too many edge cases, that's why I recommend using an existing approach. There is no need to reinvent the wheel.

let arr = [JSON.stringify({r: 0, g: 1})]
let obj = {g: 1, r: 0}

console.log(arr.includes(JSON.stringify(obj)));

let arr2 = [{r:0, g:1}];
let obj2 = {g:1, r:0};

console.log(arr2.some(item => _.isEqual(item, obj2)));
console.log(_.some(arr2, item => _.isEqual(item, obj2))); // more canonical way
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>

Related