3

I have the following function:

function containsObject(object, array) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] === object) {
            return i;
        }
    }

    return false;
}

The following array:

var array = [
    {
        name: 'test1',
        age: 12
    },
    {
        name: 'test2',
        age: 14
    }
];

And I need to check if the following object is in the array:

var object = {
    name: 'test1',
    age: 12
};

But when I use the function to check if the array contains the object:

console.log(containsObject(object, array));

It will return false, since the references of the objects aren't the same. So technically speaking, the objects aren't the same.

How do I go on about this without sharing references?

3
  • youll have to check each element of the object with each element of the other object Commented May 13, 2016 at 13:00
  • You could just stringify the Json and see if the array json string contains the object json string. Commented May 13, 2016 at 13:02
  • JSON.stringify(array).contains(JSON.stringify(object)); Should work in your usecase IMO. Commented May 13, 2016 at 13:08

4 Answers 4

2

Fiddle : https://jsfiddle.net/thatOneGuy/3ys6s7sy/2/

Youll have to check each element of the object with each element of the other object.

function containsObject(object, array) {
  for (var i = 0; i < array.length; i++) {
    var count = 0;
    var matching = true;
    for (var key in object) {
      if (array[i][key] === object[key]) {
        matching = true;
        if (count == Object.keys(array[i]).length - 1 && matching) {
          return i;
        } else {
          count++;
        }
      } else {
        matching = false;

      }
    }
  }
  return false;
}

var array = [{
  name: 'test2',
  age: 14
}, {
  name: 'test1',
  age: 12
}];

var thisObject = {
  name: 'test1',
  age: 12
};

console.log(containsObject(thisObject, array));

I changed the data around to see if it works. It now logs 'i' correctly. This would be quite slow if you have a lot of data to compare. You can always stringify the two objects and compare the two strings ?

Here is that function :

function containsObject(object, array) {
  for (var i = 0; i < array.length; i++) {
    for (var key in object) {
      //if (array[i][key] === object[key]) {
      //  return i;
      //}
      if (JSON.stringify(array[i]) === JSON.stringify(object)) {
            return i;
        }
    }
  }
  return false;
}

As mentioned in the comments the first one wouldn't cater for deep comparison. Whereas the stringify would. I would be careful about the objects being in different order though. For example if you use this object :

var thisObject = {
  age: 12,
  name: 'test1'
};

To compare, it wouldn't work as its just a straight string comparison.

Fiddle with stringify : https://jsfiddle.net/thatOneGuy/3ys6s7sy/1/

Sign up to request clarification or add additional context in comments.

4 Comments

Shouldn't you check for the value too ? since the OP wants to check for the full object and not the JSON structure.
It doesn't do a deep comparison.
Wouldn't this check for the first key that matches the object's and return i right now?
@AuditeMarlow editted answer, won't return straight away now :)
0

It's probably best done by an invention of Array.prototype.contains(). So let's invent it. However i will take use of my previous inventions Object.prototype.compare() and Array.prototype.compare()

Object.prototype.compare = function(o){
  var ok = Object.keys(this);
  return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
Array.prototype.compare = function(a){
  return this.every((e,i) => typeof a[i] === "object" ? a[i].compare(e) : a[i] === e);
};
Array.prototype.contains = function(o){
  return this.some(e => typeof o === "object" ? o.compare(e) : o === e);
}

var arr = [
           {
            name: 'test1',
             age: 12
           },
           {
            name: 'test2',
             age: 14
           }
          ],
   obj1 = {
           name: 'test1',
            age: 12
          },
   obj2 = {
           name: 'test1',
            age: 11
          }, 
   arr2 = [1,2,3];

document.writeln(arr.contains(obj1));
document.writeln(arr.contains(obj2));
document.writeln(arr2.contains(3));
document.writeln(arr2.contains(4));

Well of course you can you can also modify it to get you the index or a reference of the found match.

Comments

0

The solution using Object.keys and Array.sort functions.
I've extended your initial array a bit to get a more complex example:

function containsObject(object, array) {
    var props = Object.keys(object),
        len = array.length,
        props_count = props.length, inner_obj, inner_props, inArray = false;
    props.sort();

    while (len--) {
        inner_obj = array[len];
        inner_props = Object.keys(inner_obj);
        inner_props.sort();
        if (props_count === inner_props.length) {
            while (props_count--) {
                if (object[props[props_count]] !== inner_obj[inner_props[props_count]]) {
                    break;
                }
                inArray = true;
            }
            if (inArray) return len;  // return array key which has an equal object
            props_count = props.length;
        }
    }

    return false;
}

var array = [{ name: 'test3', age: 12 }, { name: 'test2',  age: 14 }, { name: 'test1',  age: 12 }],
    object = { name: 'test1', age: 12 };

console.log(containsObject(object, array));  // 2 - appropriate key

Comments

0

I ended up going with thatOneGuy's solution, altering it so it can search both arrays and objects:

function containsObject(needle, haystack) {
    for (var i in haystack) {
        var count    = 0,
            matching = true;

        for (var key in needle) {
            if (haystack[i][key] === needle[key]) {
                matching = true;

                if (count == Object.keys(haystack[i]).length - 1 && matching) {
                    return i;
                } else {
                    count++;
                }
            } else {
                matching = false;
            }
        }
    }

    return false;
}

4 Comments

You may prefer to check this answer of mine. Probably your solution is there.. Object.prototype.compare() and Array.prototype.compare() stackoverflow.com/a/37173585/4543207
I would be careful with stringify, see my added answer (added before you put this). Be careful what order you have the objects in as it's a straight string comparison, it doesn't go and find the value of the object at a certain key. @Redu answer seems to solve it more efficiently and precisely.
It won't work when the order of properties in the object is different.
Updated the answer so it does now.

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.