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?

Audite Marlow
  • 1,034
  • 1
  • 7
  • 25

4 Answers4

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/

thatOneGuy
  • 9,977
  • 7
  • 48
  • 90
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;
}
Audite Marlow
  • 1,034
  • 1
  • 7
  • 25
  • You may prefer to check this answer of mine. Probably your solution is there.. `Object.prototype.compare()` and `Array.prototype.compare()` http://stackoverflow.com/a/37173585/4543207 – Redu May 13 '16 at 13:13
  • 1
    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. – thatOneGuy May 13 '16 at 13:13
  • It won't work when the order of properties in the object is different. – Dmitri Pavlutin May 13 '16 at 13:21
  • Updated the answer so it does now. – Audite Marlow May 18 '16 at 08:01
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.

Redu
  • 25,060
  • 6
  • 56
  • 76
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
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105