0

I want to use indexOf() on an array of objects. For example:

var arr;
var arr[0] = {a: 1, b: 2};
var arr[1] = {a: 1, b: 3};
var obj = {a: 1, b: 2};
console.log(arr.indexOf(obj));

This will print -1 because arr[0] does not equal obj. How can I make this work (i.e., print 0)?

asked Aug 22, 2019 at 23:26
3
  • 2
    Possible duplicate of Object comparison in JavaScript Commented Aug 22, 2019 at 23:30
  • It doesn't work because you can't compare objects directly. Commented Aug 22, 2019 at 23:31
  • 1
    You are comparing objects instance but here you have two distinct instances of object that happens to have same properties. obj = arr[0]; console.log(arr.indexOf(obj));0 Commented Aug 22, 2019 at 23:41

3 Answers 3

1

You would have to compare the properties. Something like this would work:

var arr = [];
arr[0] = {a: 1, b: 2};
arr[1] = {a: 1, b: 3};
console.log(arr.findIndex(o => o.a === 1 && o.b === 2));
//0
console.log(arr.findIndex(o => o.a === 1 && o.b === 3));
//1

answered Aug 22, 2019 at 23:30
Sign up to request clarification or add additional context in comments.

Comments

0

The array.findIndex() function will bring back the index for the first value that the comparing function results are true. I have a function that I use to compare if two objects are equal that can be used in this example.

var obj = {a: 1, b: 2};
var arr = [];
arr[0] = {a: 1, b: 2};
arr[1] = {a: 1, b: 3};
var idx = arr.findIndex(element => areObjsEqual(element,obj));
console.log(`The index is: ${idx}`);
//Function to check if two js objects are equal
function areObjsEqual(a, b) {
 // Create arrays of property names
 var aProps = Object.getOwnPropertyNames(a);
 var bProps = Object.getOwnPropertyNames(b);
 // If number of properties is different,
 // objects are not equivalent
 if (aProps.length != bProps.length) { return false;}
 
 //loop through the object and compare the property values
 for (var i = 0; i < aProps.length; i++) {
 var propName = aProps[i];
 // If values of same property are not equal,
 // objects are not equivalent
 if (a[propName] !== b[propName]) {
 return false;
 }
 }
 // If we made it this far, objects
 // are considered equivalent
 return true;
}

answered Aug 23, 2019 at 0:02

Comments

0

I created a similar function which compares almost anything, a while back:

function similar(needle, haystack, exact){
 if(needle === haystack){
 return true;
 }
 if(needle instanceof Date && haystack instanceof Date){
 return needle.getTime() === haystack.getTime();
 }
 if(!needle || !haystack || (typeof needle !== 'object' && typeof haystack !== 'object')){
 return needle === haystack;
 }
 if(needle === null || needle === undefined || haystack === null || haystack === undefined || needle.prototype !== haystack.prototype){
 return false;
 }
 var keys = Object.keys(needle);
 if(exact && keys.length !== Object.keys(haystack).length){
 return false;
 }
 return keys.every(function(k){
 return similar(needle[k], haystack[k]);
 });
}
var obj1 = {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'};
var obj2 = {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'};
console.log(similar(obj1, obj2, true)); // true for exact match
obj2.newProp = 'new value'; // extra haystack prop added
console.log(similar(obj1, obj2, true)); // true for exact - result is false here
console.log(similar(obj1, obj2)); // not exact - obj1 properties and values are in obj2

Of course similar can be made to find the similarIndex of a needle (anything) in an haystack (array of anything), like so:

function similar(needle, haystack, exact){
 if(needle === haystack){
 return true;
 }
 if(needle instanceof Date && haystack instanceof Date){
 return needle.getTime() === haystack.getTime();
 }
 if(!needle || !haystack || (typeof needle !== 'object' && typeof haystack !== 'object')){
 return needle === haystack;
 }
 if(needle === null || needle === undefined || haystack === null || haystack === undefined || needle.prototype !== haystack.prototype){
 return false;
 }
 var keys = Object.keys(needle);
 if(exact && keys.length !== Object.keys(haystack).length){
 return false;
 }
 return keys.every(function(k){
 return similar(needle[k], haystack[k]);
 });
}
function similarIndex(needle, haystack, exact){
 for(var i=0,l=haystack.length; i<l; i++){
 if(similar(needle, haystack[i], exact)){
 return i;
 }
 }
 return -1;
}
var objArray = [{a:1, b:[5, 'wtf'], c:{another:'cool', neat:'not', num:1}, d:'simple string'}, {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'}, {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:4}, d:'simple string'}];
var testObj = {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'};
console.log(similarIndex(testObj, objArray, true)); // exact - index is 1 in this case
objArray[1].newProp = 'new value'; // haystack array element 1 gets new property and value
console.log(similarIndex(testObj, objArray, true)); // exact - -1 result here
console.log(similarIndex(testObj, objArray)); // not exact - index 1

answered Aug 23, 2019 at 0:26

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.