How to determine if object is in array [duplicate]

I need to determine if an object already exists in an array in javascript.

eg (dummycode):

var carBrands = [];

var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};

carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);

now the "carBrands" array contains all instances. I'm now looking a fast solution to check if an instance of car1, car2, car3 or car4 is already in the carBrands array.

eg:

var contains =  carBrands.Contains(car1); //<--- returns bool.

car1 and car4 contain the same data but are different instances they should be tested as not equal.

Do I have add something like a hash to the objects on creation? Or is there a faster way to do this in Javascript.

I am looking for the fastest solution here, if dirty, so it has to be ;) In my app it has to deal with around 10000 instances.

no jquery

Answers:

Answer

Having been recently bitten by the FP bug reading many wonderful accounts of how neatly the functional paradigm fits with Javascript

I replicate the code for completeness sake and suggest two ways this can be done functionally.

    var carBrands = [];

  var car1 = {name:'ford'};
  var car2 = {name:'lexus'};
  var car3 = {name:'maserati'};
  var car4 = {name:'ford'};
  var car5 = {name:'toyota'};

  carBrands.push(car1);
  carBrands.push(car2);
  carBrands.push(car3);
  carBrands.push(car4);

  // ES6 approach which uses the includes method (Chrome47+, Firefox43+)

  carBrands.includes(car1) // -> true
  carBrands.includes(car5) // -> false

If you need to support older browsers use the polyfill, it seems IE9+ and Edge do NOT support it. Located in polyfill section of MSDN page

Alternatively I would like to propose an updated answer to cdhowie

// ES2015 syntax
function containsObject(obj, list) {

    return list.some(function(elem) {
      return elem === obj
    })
}

// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {

    return list.some(elem => elem === obj)
}
Answer

try Array.prototype.some()

MDN Array.prototype.some


    function isBiggerThan10(element, index, array) {
      return element > 10;
    }
    [2, 5, 8, 1, 4].some(isBiggerThan10);  // false
    [12, 5, 8, 1, 4].some(isBiggerThan10); // true

Answer

I used underscore javascript library to tweak this issue.

function containsObject(obj, list) {
 var res = _.find(list, function(val){ return _.isEqual(obj, val)});
 return (_.isObject(res))? true:false;
}

please refer to underscore.js documentation for the underscore functions used in the above example.

note: This is not a pure javascript solution. Shared for educational purposes.

Answer

I would use a generic iterator of property/value over the array. No jQuery required.

arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];

objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true

function objectPropInArray(list, prop, val) {
  if (list.length > 0 ) {
    for (i in list) {
      if (list[i][prop] === val) {
        return true;
      }
    }
  }
  return false;  
}
Answer

You could try sorting the array based on a property, like so:

carBrands = carBrands.sort(function(x,y){
  return (x == y) ? 0 : (x > y) ? 1 : -1;
});

Then you can use an iterative routine to check whether

carBrands[Math.floor(carBrands.length/2)] 
// change carBrands.length to a var that keeps 
// getting divided by 2 until result is the target 
// or no valid target exists

is greater or lesser than the target, and so on, which will let you go through the array quickly to find whether the object exists or not.

Answer

This function is to check for a unique field. Arg 1: the array with selected data Arg 2: key to check Arg 3: value that must be "validated"

function objectUnique( array, field, value )
{
    var unique = true;
    array.forEach(function ( entry )
    {
        if ( entry[field] == value )
        {
            unique = false;
        }
    });

    return unique;
}
Answer

Use something like this:

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

    return false;
}

In this case, containsObject(car4, carBrands) is true. Remove the carBrands.push(car4); call and it will return false instead. If you later expand to using objects to store these other car objects instead of using arrays, you could use something like this instead:

function containsObject(obj, list) {
    var x;
    for (x in list) {
        if (list.hasOwnProperty(x) && list[x] === obj) {
            return true;
        }
    }

    return false;
}

This approach will work for arrays too, but when used on arrays it will be a tad slower than the first option.

Answer

Why don't you use the indexOf method of javascript arrays?

Check this out: MDN indexOf Arrays

Simply do:

carBrands.indexOf(car1);

It will return you the index (position in the array) of car1. It will return -1 if car1 was not found in the array.

http://jsfiddle.net/Fraximus/r154cd9o

Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object. As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures.
If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.

Answer

You could use jQuery's grep method:

$.grep(carBrands, function(obj) { return obj.name == "ford"; });

But as you specify no jQuery, you could just make a derivative of the function. From the source code:

function grepArray( elems, callback, inv ) {  
    var ret = [];  

    // Go through the array, only saving the items  
    // that pass the validator function  
    for ( var i = 0, length = elems.length; i < length; i++ ) {  
        if ( !inv !== !callback( elems[ i ], i ) ) {  
            ret.push( elems[ i ] );  
        }  
    }  

    return ret;  
}  

grepArray(carBrands, function(obj) { return obj.name == "ford"; });
Answer

You can just use the equality operator: ==. Objects are checked by reference by default, so you don't even need to use the === operator.

try this, just make sure you're using the correct variable reference in the place of car1:

var i, car, l = cars.length;

for (i = 0; i < l; i++)
{
  if ((car = cars[i]) == car1)
  {
    break;
  }
  else car = null;
}

Edit to add:

An array extension was mentioned, so here's the code for it:

Array.prototype.contains = Array.prototype.contains || function(obj)
{
  var i, l = this.length;
  for (i = 0; i < l; i++)
  {
    if (this[i] == obj) return true;
  }
  return false;
};

Note that I'm caching the length value, as the Array's length property is actually an accessor, which is marginally slower than an internal variable.

Answer

i know this is an old post, but i wanted to provide a JQuery plugin version and my code.

// Find the first occurrence of object in list, Similar to $.grep, but stops searching 
function findFirst(a,b){
var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined;
}

usage:

var product = $.findFirst(arrProducts, function(p) { return p.id == 10 });

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.