Home How do I check if an array includes an object in JavaScript?
Reply: 29

How do I check if an array includes an object in JavaScript?

brad
1#
brad Published in 2008-10-25 22:14:40Z

What is the most concise and efficient way to find out if a JavaScript array contains an object?

This is the only way I know to do it:

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

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.

Glomek
2#
Glomek Reply to 2017-10-15 00:56:15Z

Current browsers have Array#includes, which does exactly that, is widely supported, and has a polyfill for older browsers.

You can also use Array#indexOf, which is less direct, but doesn't require Polyfills for out of date browsers.

jQuery offers $.inArray, which is functionally equivalent to Array#indexOf.

underscore.js, a JavaScript utility library, offers _.contains(list, value), alias _.include(list, value), both of which use indexOf internally if passed a JavaScript array.

Some other frameworks offer similar methods:

  • Dojo Toolkit: dojo.indexOf(array, value, [fromIndex, findLast])
  • Prototype: array.indexOf(value)
  • MooTools: array.indexOf(value)
  • MochiKit: findValue(array, value)
  • MS Ajax: array.indexOf(value)
  • Ext: Ext.Array.contains(array, value)
  • Lodash: _.includes(array, value, [from]) (is _.contains prior 4.0.0)
  • ECMAScript 2016: array.includes(value)

Notice that some frameworks implement this as a function, while others add the function to the array prototype.

Peter Mortensen
3#
Peter Mortensen Reply to 2011-08-11 23:41:11Z

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

Bill the Lizard
4#
Bill the Lizard Reply to 2012-07-26 15:30:44Z

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
Peter Mortensen
5#
Peter Mortensen Reply to 2017-01-07 11:36:05Z

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;
      };
}
Peter Mortensen
6#
Peter Mortensen Reply to 2011-08-11 23:43:55Z

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.

Ken
7#
Ken Reply to 2009-08-27 17:10:53Z

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.

MattMcKnight
8#
MattMcKnight Reply to 2017-02-28 04:29:16Z

Thinking out of the box for a second, if you are in making this call many many times, it is vastly more efficient to use an associative array a Map to do lookups using a hash function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Dennis Allen
9#
Dennis Allen Reply to 2010-08-04 14:05:17Z

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;
}
Ztyx
10#
Ztyx Reply to 2011-02-05 18:02:43Z

If you are checking repeatedly for existence of an object in an array you should maybe look into

  1. Keeping the array sorted at all times by doing insertion sort in your array (put new objects in on the right place)
  2. Make updating objects as remove+sorted insert operation and
  3. Use a binary search lookup in your contains(a, obj).
Community
11#
Community Reply to 2017-05-23 12:18:36Z

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.

Peter Mortensen
12#
Peter Mortensen Reply to 2017-01-07 11:32:23Z

Use:

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, but sometimes it's OK (if you are aware of it and the trade-off).

Peter Mortensen
13#
Peter Mortensen Reply to 2017-01-07 11:31:00Z

b is the value, and a is the array. It returns true or false:

function(a, b) {
    return a.indexOf(b) != -1
}
Peter Mortensen
14#
Peter Mortensen Reply to 2017-01-07 11:30:42Z

While array.indexOf(x)!=-1 is the most concise way to do this (and has been supported by non-Internet Explorer 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.)

mpromonet
15#
mpromonet Reply to 2014-09-06 16:22:05Z
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Returns array index if found, or -1 if not found

Andy Rohr
16#
Andy Rohr Reply to 2012-11-23 16:44:57Z

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)]
Simon_Weaver
17#
Simon_Weaver Reply to 2013-08-03 18:10:31Z

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;
    }
}
stamat
18#
stamat Reply to 2013-09-11 17:24:46Z

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));
Peter Mortensen
19#
Peter Mortensen Reply to 2017-01-07 11:29:04Z

Use:

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

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
Community
20#
Community Reply to 2017-05-23 12:03:09Z

Use:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

Demo

To know exactly what the tilde ~ do at this point, refer to this question What does a tilde do when it precedes an expression?.

Peter Mortensen
21#
Peter Mortensen Reply to 2017-01-07 11:27:22Z

ECMAScript 6 has an elegant proposal on find.

The find method executes the callback function once for each element present in the array until it finds one where callback returns a true value. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined. callback is invoked only for indexes of the array which have assigned values; it is not invoked for indexes which have been deleted or which have never been assigned values.

Here is the MDN documentation on that.

The find functionality works like this.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

You can use this in ECMAScript 5 and below by defining the function.

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}
Eduardo Cuomo
22#
Eduardo Cuomo Reply to 2014-06-15 01:15:33Z

I use the following:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false
Michael
23#
Michael Reply to 2018-01-11 07:26:57Z

You can use Array.prototype.some()

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

Upside to this is that the iteration is aborted once the element is found so unnecessary iteration cycles are saved.

One thing to note is that some() is not present in all js versions: (from the website)

some was added to the ECMA-262 standard in the 5th edition; as such it may not be present in all implementations of the standard

You can use it in Node.js without any issue. If you need to support all browsers then there's this polyfill (from the same link):

if (!Array.prototype.some)
{
  Array.prototype.some = function(fun /*, thisArg */)
  {
    'use strict';

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function')
      throw new TypeError();

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t && fun.call(thisArg, t[i], i, t))
        return true;
    }

    return false;
  };
}
dr.dimitru
24#
dr.dimitru Reply to 2014-09-10 12:12:52Z

We use this snippet (works with objects, arrays, strings):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Usage:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false
dansalmo
25#
dansalmo Reply to 2014-09-12 16:55:36Z
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some() was added to the ECMA-262 standard in the 5th edition

Oriol
26#
Oriol Reply to 2016-02-08 16:53:32Z

ECMAScript 7 introduces Array.prototype.includes.

It can be used like this:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

It also accepts an optional second argument fromIndex:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

Unlike indexOf, which uses Strict Equality Comparison, includes compares using SameValueZero equality algorithm. That means that you can detect if an array includes a NaN:

[1, 2, NaN].includes(NaN); // true

Also unlike indexOf, includes does not skip missing indices:

new Array(5).includes(undefined); // true

Currently it's still a draft but can be polyfilled to make it work on all browsers.

Peter Mortensen
27#
Peter Mortensen Reply to 2017-01-07 11:25:51Z

One-liner:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
Peter Mortensen
28#
Peter Mortensen Reply to 2017-01-07 11:42:35Z

A hopefully faster bidirectional indexOf / lastIndexOf alternative

2015

While the new method includes is very nice, the support is basically zero for now.

It's long time that I was thinking of way to replace the slow indexOf/lastIndexOf functions.

A performant way has already been found, looking at the top answers. From those I chose the contains function posted by @Damir Zekic which should be the fastest one. But it also states that the benchmarks are from 2008 and so are outdated.

I also prefer while over for, but for not a specific reason I ended writing the function with a for loop. It could be also done with a while --.

I was curious if the iteration was much slower if I check both sides of the array while doing it. Apparently no, and so this function is around two times faster than the top voted ones. Obviously it's also faster than the native one. This in a real world environment, where you never know if the value you are searching is at the beginning or at the end of the array.

When you know you just pushed an array with a value, using lastIndexOf remains probably the best solution, but if you have to travel through big arrays and the result could be everywhere, this could be a solid solution to make things faster.

Bidirectional indexOf/lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

Performance test

http://jsperf.com/bidirectionalindexof

As test I created an array with 100k entries.

Three queries: at the beginning, in the middle & at the end of the array.

I hope you also find this interesting and test the performance.

Note: As you can see I slightly modified the contains function to reflect the indexOf & lastIndexOf output (so basically true with the index and false with -1). That shouldn't harm it.

The array prototype variant

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

The function can also be easily modified to return true or false or even the object, string or whatever it is.

And here is the while variant:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

How is this possible?

I think that the simple calculation to get the reflected index in an array is so simple that it's two times faster than doing an actual loop iteration.

Here is a complex example doing three checks per iteration, but this is only possible with a longer calculation which causes the slowdown of the code.

http://jsperf.com/bidirectionalindexof/2

l3x
29#
l3x Reply to 2015-10-21 11:58:14Z

Use lodash's some function.

It's concise, accurate and has great cross platform support.

The accepted answer does not even meet the requirements.

Requirements: Recommend most concise and efficient way to find out if a JavaScript array contains an object.

Accepted Answer:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

My recommendation:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

Notes:

$.inArray works fine for determining whether a scalar value exists in an array of scalars...

$.inArray(2, [1,2])
> 1

... but the question clearly asks for an efficient way to determine if an object is contained in an array.

In order to handle both scalars and objects, you could do this:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
Peter Mortensen
30#
Peter Mortensen Reply to 2017-01-07 11:46:13Z

One can use Set that has the method "has()":

function contains(arr, obj) {
  var proxy = new Set(arr);
  if (proxy.has(obj))
    return true;
  else
    return false;
}

var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.457074 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO