array.contains(obj) in JavaScript
70
What is the most concise and efficient way to find out if a JavaScript array contains an obj?

This is the only way I know to do it:

Is there a better and more concise way to accomplish this?

This is very closely related to Stack Overflow question Best way to find an item in a JavaScript Array? which addresses finding objects in an array using indexOf.
improve this question | comment
Russell Hane Created at: 2013-11-13 17:07:10 UTC By Russell Hane
just tested: your way is actually the fastest for across browsers: jsperf.com/find-element-in-obj-vs-array/2 (apart from pre-saving a.length in a variable) while using indexOf (as in $.inArray) is much slower - Loyce Kozey V
many have replied that the Array#indexOf is your best choice here. But if you want something that can be correctly cast to Boolean, use this: ~[1,2,3].indexOf(4) will return 0 which will evaluate as false, whereas ~[1,2,3].indexOf(3) will return -3 which will evaluate as true. - Ozella Schuppe
21 Answers
0
Just another option

// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
    for (var key in this)
        if (this[key] === value) return true;
    return false;
}

0
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
    if(array[i] == elem){return i;}
}
return -1;
} 


Reutrns the position if found, or -1 if not found
0
Here's a Javascript 1.6 compatible implementation of Array.indexOf:

if (!Array.indexOf)
{
  Array.indexOf = [].indexOf ?
      function (arr, obj, from) { return arr.indexOf(obj, from); }:
      function (arr, obj, from) { // (for IE6)
        var l = arr.length,
            i = from ? parseInt( (1*from) + (from<0 ? l:0), 10) : 0;
        i = i<0 ? 0 : i;
        for (; i<l; i++) {
          if (i in arr  &&  arr[i] === obj) { return i; }
        }
        return -1;
      };
}

0
b is the value, a is the array

It returns true or false

   function(a,b){return!!~a.indexOf(b)}

0
indexOf maybe, but it's a "JavaScript extension to the ECMA-262 standard; as such it may not be present in other implementations of the standard."

Example:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1


AFAICS Microsoft does not offer some kind of alternative to this, but you can add similar functionality to arrays in Internet Explorer (and other browsers that don't support indexOf) if you want to, as a quick Google search reveals (for example, this one).
0
Extending the JavaScript Array object is a really bad idea because you introduce new properties (your custom methods) into for-in loops which can break existing scripts. A few years ago the authors of the Prototype library had to re-engineer their library implementation to remove just this kind of thing.

If you don't need to worry about compatibility with other JavaScript running on your page, go for it, otherwise, I'd recommend the more awkward, but safer free-standing function solution.
0
Thinking out of the box for a second, if you are in making this call many many times, it is more efficient to use an associative array to do lookups using a hash function.
0
If you are checking repeatedly for existence of an object in an array you should maybe look into

Keeping the array sorted at all times by doing insertion sort in your array (put new objects in on the right place) 
Make updating objects as remove+sorted insert operation and
Use a binary search lookup in your contains(a, obj).
0
If you are using JavaScript 1.6 or later (Firefox 1.5 or later) you can use Array.indexOf.  Otherwise, I think you are going to end up with something similar to your original code.
0
While array.indexOf(x)!=-1 is the most concise way to do this (and has been supported by non-IE browsers for over decade...), it is not O(1), but rather O(N), which is terrible. If your array will not be changing, you can convert your array to a hashtable, then do table[x]!==undefined or ===undefined:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}


Demo:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})


(Unfortunately, while you can create an Array.prototype.contains to "freeze" an array and store a hashtable in this._cache in two lines, this would give wrong results if you chose to edit your array later. Javascript has insufficient hooks to let you keep this state, unlike python for example.)
0
Update: As @orip mentions in comments, the linked benchmark was done in 2008, so results may not be relevant for modern browsers. However, you probably need this to support non-modern browsers anyway and they probably haven't been updated since. Always test for yourself.

As others have said, the iteration through the array is probably the best way, but it has been proven that a decreasing while loop is the fastest way to iterate in JavaScript. So you may want to rewrite your code as follows:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}


Of course, you may as well extend Array prototype:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}


And now you can simply use the following:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

0
As others have mentioned you can use Array.indexOf, but it isn't available in all browsers. Here's the code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf to make it work the same in older browsers.


  indexOf is a recent addition to the ECMA-262 standard; as such it may
  not be present in all browsers. You can work around this by inserting
  the following code at the beginning of your scripts, allowing use of
  indexOf in implementations which do not natively support it. This
  algorithm is exactly the one specified in ECMA-262, 5th edition,
  assuming Object, TypeError, Number, Math.floor, Math.abs, and Math.max
  have their original value.


if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (this == null) {
            throw new TypeError();
        }
        var t = Object(this);
        var len = t.length >>> 0;
        if (len === 0) {
            return -1;
        }
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= len) {
            return -1;
        }
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (; k < len; k++) {
            if (k in t && t[k] === searchElement) {
                return k;
            }
        }
        return -1;
    }
}

0
Similar thing: Finds the first element by a "search lambda":

Array.prototype.find = function(search_lambda) {
  return this[this.map(search_lambda).indexOf(true)];
};


Usage:

[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4


Same in coffeescript:

Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]

0
My little contribution:

function isInArray(array, search)
{
    return (array.indexOf(search) >= 0) ? true : false; 
}

//usage
if(isInArray(my_array, "my_value"))
{
    //...
}

0
Here's how Prototype does it:

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}


Also see here for how they hook it up.
0
Literally:

(using Firefox v3.6, with for-in caveats as previously noted 
(HOWEVER the use below might endorse for-in for this very purpose! That is, enumerating array elements that ACTUALLY exist via a property index (HOWEVER, in particular, the array length property is NOT enumerated in the for-in property list!).).)

(Drag & drop the following complete URI's for immediate mode browser testing.)

javascript:

  function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}

  function check(ra){
      return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
  }
  alert([
            check([{}]), check([]), check([,2,3]),
            check(['']), '\t (a null string)', check([,,,])
        ].join('\n'));


which displays:

There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
     (a null string)
There is NO object in [,,].


Wrinkles: if looking for a "specific" object consider:

javascript: alert({}!={}); alert({}!=={});


and thus:

javascript:
  obj={prop:"value"}; ra1=[obj]; ra2=[{prop:"value"}];
  alert(ra1[0]==obj); alert(ra2[0]==obj);


Often ra2 is considered to "contain" obj as the literal entity {prop:"value"}.

A very coarse, rudimentary, naive (as in code needs qualification enhancing) solution:

javascript:
  obj={prop:"value"};   ra2=[{prop:"value"}];
  alert(
    ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
      'found' :
      'missing' );


See ref: Searching for objects in JavaScript arrays.
0
Hmmm. what about

Array.prototype.contains = function(x){
  var retVal = -1;
  //x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
  //x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }
  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }
  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}


I know it's not the best way to go, but since there is no native IComparable way to interact between objects, I guess this is as close as you can get to compare two entities in an array. Also, extending Array object might not be a wise thing to do sometimes it's ok (if you are aware of it and the trade-off)
0
Thanks @Damir Zekić. I had to compare an integer value with an array of numbers, and was able to adapt your code as follows.

  arrayContainsInteger: function (targetArray, checkValue) {
     var i = targetArray.length;
     while (i--) {
        var arrayInt = parseInt(targetArray[i], 10);
        var checkInt = parseInt(checkValue, 10);
        if (arrayInt === checkInt) {
           return true;
        }
     }
     return false;
  },


The above was needed because the following evaluation was always returning -1, even when the target array contained multiple matching numbers.

if ($.inArray(parseInt(myID, 10), arrayOfIDs) == -1)

0
function inarray(o, a){return !!(a.indexOf(o)+1)}

0
I looked through submitted answers and got that they only apply if you search for the object via reference. A simple linear search with reference object comparison. 

But lets say you don't have the reference to an object, how will you find the correct object in the array? You will have to go linearly and deep compare with each object. Imagine if the list is too large, and the objects in it are very big containing big pieces of text. The performance drops drastically with the number and size of the elements in the array.

You can stringify objects and put them in the native hash table, but then you will have data redundancy remembering these keys cause JavaScript keeps them for 'for i in obj', and you only want to check if the object exists or not, that is, you have the key.

I thought about this for some time constructing a JSON Schema validator, and I devised a simple wrapper for the native hash table, similar to the sole hash table implementation, with some optimization exceptions which I left to the native hash table to deal with. It only needs performance benchmarking...
All the details and code can be found on my blog: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/
I will soon post benchmark results. 

The complete solution works like this:

var a = {'a':1,
 'b':{'c':[1,2,[3,45],4,5],
 'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
 'u':'lol'},
 'e':2};

 var b = {'a':1, 
 'b':{'c':[2,3,[1]],
 'd':{'q':3,'b':{'b':3}}},
 'e':2};

 var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

 var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init

 hc.put({a:1, b:1});
 hc.put({b:1, a:1});
 hc.put(true);
 hc.put('true');
 hc.put(a);
 hc.put(c);
 hc.put(d);
 console.log(hc.exists('true'));
 console.log(hc.exists(a));
 console.log(hc.exists(c));
 console.log(hc.exists({b:1, a:1}));
 hc.remove(a);
 console.log(hc.exists(c));

0
Modern browsers have Array#indexOf, which does exactly that; this is in the new(ish) ECMAScript 5th edition specification, but it has been in several browsers for years. Older browsers can be supported using the code listed in the "compatibility" section at the bottom of that page.

jQuery has a utility function for this:

$.inArray(value, array)


It returns the index of a value in an array. It returns -1 if the array does not contain the value.

jQuery has several useful utility functions. 

An excellent JavaScript utility library is underscore.js:

_.contains(list, value), alias _.include(list, value) (underscore's contains/include  uses indexOf internally if passed a JavaScript array). 
Some other frameworks:

Dojo Toolkit: dojo.indexOf(array, value, [fromIndex, findLast]) documentation. Dojo has a lot of utility functions, see http://api.dojotoolkit.org.
Prototype: array.indexOf(value) documentation
MooTools: array.indexOf(value) documentation
MochiKit: findValue(array, value) documentation
MS Ajax: array.indexOf(value) documentation
Ext: Ext.Array.indexOf(array, value, [from]) documentation
Notice how some frameworks implement this as a function. While other frameworks add the function to the array prototype.

Languages that compile to javascript

In coffeescript, the in operator is the equivalent of contains:

a = [1, 2, 3, 4]
alert(2 in a)


Dart:

var mylist = [1, 2, 3];
assert(mylist.contains(1));
assert(mylist.indexOf(1) == 0);

Your Answer