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)?

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

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;
}

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

Comments

Your Answer

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.