How do I check if an array includes a value in JavaScript?


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

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.

Modern browsers have Array#includes, which does exactly that and is widely supported by everyone except IE:

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

You can also use Array#indexOf, which is less direct, but doesn't require polyfills for outdated browsers.


Many frameworks also offer similar methods:

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


Update from 2019: This answer is from 2008 (11 years old!) and is not relevant for modern JS usage. The promised performance improvement was based on a benchmark done in browsers of that time. It might not be relevant to modern JS execution contexts. If you need an easy solution, look for other answers. If you need the best performance, benchmark for yourself in the relevant execution environments.

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

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


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.


The top answers assume primitive types but if you want to find out if an array contains an object with some trait, Array.prototype.some() is a very elegant solution:

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

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

The nice thing about it is that the iteration is aborted once the element is found so unnecessary iteration cycles are spared.

Also, it fits nicely in an if statement since it returns a boolean:

if (items.some(item => item.a === '3')) {
  // do something
}

* As jamess pointed out in the comment, at the time of this answer, September 2018, Array.prototype.some() is fully supported: caniuse.com support table


Let's say you've defined an array like so:

const array = [1, 2, 3, 4]

Below are three ways of checking whether there is a 3 in there. All of them return either true or false.

Native Array method (since ES2016) (compatibility table)

array.includes(3) // true

As custom Array method (pre ES2016)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

Simple function

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

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;
        };
}

Use:

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

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

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.


Thinking out of the box for a second, if you are 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


One-liner:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

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

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


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


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


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

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.


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

Solution that works in all modern browsers:

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

Usage:

contains([{a: 1}, {a: 2}], {a: 1}); // true

IE6+ solution:

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

Usage:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Why to use JSON.stringify?

Array.indexOf and Array.includes (as well as most of the answers here) only compare by reference and not by value.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

Bonus

Non-optimized ES6 one-liner:

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

Note: Comparing objects by value will work better if the keys are in the same order, so to be safe you might sort the keys first with a package like this one: https://www.npmjs.com/package/sort-keys


Updated the contains function with a perf optimization. Thanks itinance for pointing it out.


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)

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;
    }
  });
}

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


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


Performance

Today 2019.01.07 I perform tests on MacOs HighSierra 10.13.6 on Chrome v78.0.0, Safari v13.0.4 and Firefox v71.0.0 for 15 chosen solutions. Conclusions

  • solutions based on JSON, Set and surprisingly find (K,N,O) are slowest on all browsers
  • the es6 includes (F) is fast only on chrome
  • the solutions based on for (C,D) and indexOf (G,H) are quite-fast on all browsers on small and big arrays so probably they are best choice for efficient solution
  • the solutions where index decrease during loop, (B) is slower probably because the way of CPU cache works.
  • I also run test for big array when searched element was on position 66% of array length, and solutions based on for (C,D,E) gives similar results (~630 ops/sec - but the E on safari and firefox was 10-20% slower than C and D)

Results

enter image description here

Details

I perform 2 tests cases: for array with 10 elements, and array with 1 milion elements. In both cases we put searched element in the array middle.

let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')}  's7'-${f(arr,'s7')}  6-${f(arr,6)} 's3'-${f(arr,'s3')}`)

let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;

function A(a, val) {
    var i = -1;
    var n = a.length;
    while (i++<n) {
       if (a[i] === val) {
           return true;
       }
    }
    return false;
}

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

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

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

function E(a, val){  
  var n = a.length-1;
  var t = n/2;
  for (var i = 0; i <= t; i++) {
        if (a[i] === val || a[n-i] === val) return true;
  }
  return false;
}

function F(a,val) {
	return a.includes(val);
}

function G(a,val) {
	return a.indexOf(val)>=0;
}

function H(a,val) {
	return !!~a.indexOf(val);
}

function I(a, val) {
  return a.findIndex(x=> x==val)>=0;
}

function J(a,val) {
	return a.some(x=> x===val);
}

function K(a, val) {
  const s = JSON.stringify(val);
  return a.some(x => JSON.stringify(x) === s);
}

function L(a,val) {
	return !a.every(x=> x!==val);
}

function M(a, val) {
  return !!a.find(x=> x==val);
}

function N(a,val) {
	return a.filter(x=>x===val).length > 0;
}

function O(a, val) {
  return new Set(a).has(val);
}

log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!

Array small - 10 elements

You can perform tests in your machine HERE

enter image description here

Array big - 1.000.000 elements

You can perform tests in your machine HERE

enter image description here


OK, you can just optimise your code to get the result!

There are many ways to do this which are cleaner and better, but I just wanted to get your pattern and apply to that using JSON.stringify, just simply do something like this in your case:

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

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'));


Surprised that this question still doesn't have latest syntax added, adding my 2 cents.

Let's say we have array of Objects arrObj and we want to search obj in it.

Array.prototype.indexOf -> (returns index or -1) is generally used for finding index of element in array. This can also be used for searching object but only works if you are passing reference to same object.

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype.includes -> (returns true or false)

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype.find -> (takes callback, returns first value/object that returns true in CB).

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype.findIndex -> (takes callback, returns index of first value/object that returns true in CB).

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

Since find and findIndex takes a callback, we can be fetch any object(even if we don't have the reference) from array by creatively setting the true condition.


Simple solution for this requirement is using find()

If you're having array of objects like below,

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

Then you can check whether the object with your value is already present or not

let data = users.find(object => object['id'] === '104');

if data is null then no admin, else it will return the existing object like below.

{id: "104", name: "admin"}

Then you can find the index of that object in the array and replace the object using below code.

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);

you will get value like below

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];

hope this will help anyone.


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.


By no means the best, but I was just getting creative and adding to the repertoire.

Do not use this

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));


    function countArray(originalArray) {
     
    	var compressed = [];
    	// make a copy of the input array
    	var copyArray = originalArray.slice(0);
     
    	// first loop goes over every element
    	for (var i = 0; i < originalArray.length; i++) {
     
    		var count = 0;	
    		// loop over every element in the copy and see if it's the same
    		for (var w = 0; w < copyArray.length; w++) {
    			if (originalArray[i] == copyArray[w]) {
    				// increase amount of times duplicate is found
    				count++;
    				// sets item to undefined
    				delete copyArray[w];
    			}
    		}
     
    		if (count > 0) {
    			var a = new Object();
    			a.value = originalArray[i];
    			a.count = count;
    			compressed.push(a);
    		}
    	}
     
    	return compressed;
    };
    
    // It should go something like this:
    
    var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
    var newArray = countArray(testArray);
    console.log(newArray);