Determine whether an array contains a value
Solution 1
var contains = function(needle) {
// Per spec, the way to identify NaN is that it is not equal to itself
var findNaN = needle !== needle;
var indexOf;
if(!findNaN && typeof Array.prototype.indexOf === 'function') {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function(needle) {
var i = -1, index = -1;
for(i = 0; i < this.length; i++) {
var item = this[i];
if((findNaN && item !== item) || item === needle) {
index = i;
break;
}
}
return index;
};
}
return indexOf.call(this, needle) > -1;
};
You can use it like this:
var myArray = [0,1,2],
needle = 1,
index = contains.call(myArray, needle); // true
Solution 2
jQuery has a utility function for this:
$.inArray(value, array)
Returns index of value
in array
. Returns -1
if array
does not contain value
.
See also How do I check if an array includes an object in JavaScript?
Solution 3
This is generally what the indexOf() method is for. You would say:
return arrValues.indexOf('Sam') > -1
Solution 4
Array.prototype.includes()
In ES2016, there is Array.prototype.includes()
.
The
includes()
method determines whether an array includes a certain element, returningtrue
orfalse
as appropriate.
Example
["Sam", "Great", "Sample", "High"].includes("Sam"); // true
Support
According to kangax and MDN, the following platforms are supported:
- Chrome 47
- Edge 14
- Firefox 43
- Opera 34
- Safari 9
- Node 6
Support can be expanded using Babel (using babel-polyfill
) or core-js
. MDN also provides a polyfill:
if (![].includes) {
Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
'use strict';
var O = Object(this);
var len = parseInt(O.length) || 0;
if (len === 0) {
return false;
}
var n = parseInt(arguments[1]) || 0;
var k;
if (n >= 0) {
k = n;
} else {
k = len + n;
if (k < 0) {k = 0;}
}
var currentElement;
while (k < len) {
currentElement = O[k];
if (searchElement === currentElement ||
(searchElement !== searchElement && currentElement !== currentElement)) {
return true;
}
k++;
}
return false;
};
}
Solution 5
It's almost always safer to use a library like lodash simply because of all the issues with cross-browser compatibilities and efficiency.
Efficiency because you can be guaranteed that at any given time, a hugely popular library like underscore will have the most efficient method of accomplishing a utility function like this.
_.includes([1, 2, 3], 3); // returns true
If you're concerned about the bulk that's being added to your application by including the whole library, know that you can include functionality separately:
var includes = require('lodash/collections/includes');
NOTICE: With older versions of lodash, this was _.contains()
rather than _.includes()
.
Prasad
Updated on November 05, 2020Comments
-
Prasad over 3 years
I need to determine if a value exists in an array.
I am using the following function:
Array.prototype.contains = function(obj) { var i = this.length; while (i--) { if (this[i] == obj) { return true; } } return false; }
The above function always returns false.
The array values and the function call is as below:
arrValues = ["Sam","Great", "Sample", "High"] alert(arrValues.contains("Sam"));
-
RaYell almost 15 yearsNote that indexOf on arrays is not implemented in IE, but you can define it yourself
-
Christoph almost 15 yearsyou should use a typed comparison with
===
to be compatible with the native implementation -
eyelidlessness almost 15 yearsThat's redundant.
-
Prasad almost 15 yearsI have tried all the answers given , but still returning false.
-
Prasad almost 15 yearsFinally its worked. its due to improper trim of the comparing value. there was some space in the comparing value
-
rlovtang almost 15 yearsMaybe, but it makes your code cleaner. if (myArray.contains(obj)) is easier to read and states the intent better than if (myArray.indexOf(obj) > -1). I definitively would implement both.
-
Greg Bernhardt about 13 yearsDon't let the name "inArray" fool you. As mentioned above (but of course I didn't read closely enough), returns -1 (not false) if the element doesn't exist.
-
Vivian River about 12 yearsWhat version of IE does this answer refer to?
-
Sahat Yalkabov over 11 yearsIsn't this technique of augmenting built-in types frowned upon?
-
Trevor over 11 yearsDoes this work in all browsers? Or do some browsers consider the index of "2" and 2 the same?
-
Eamon Nerbonne over 11 yearsBuggy:
[1,2,4].contains([].contains)
is true. Also unnecessarily slow due to the same bug. Avoid for..in over arrays. -
Trevor over 11 years@Eamon Nerbonne: I just pasted that code into jsfiddle.net and got false. Am I doing something wrong. Also, could you elaborate on how this bug slows the code down? Finally, I wasn't aware that there is a performance difference for "for..in" loops. Could you explain or direct me towards an article where I could read more?
-
naugtur about 11 years@threed totally untrue: "This is a very common practice and is used extensively by jQuery" - they create new prototypes for some objects they use, but NOT modify built-in prototypes
-
the system about 11 yearsThe shim should test if
i
is a property ofthis
. -
wilsjd about 11 yearsNote that in Sharepoint 2010, WebParts can break if you implement an Array.Prototype: labs.steveottenad.com/type-mismatch-on-wpadder-js
-
Jeffz almost 11 years@Steve Paul what is wrong with name? it does what it says: -1=it's NOT there, anything else= it's there
-
eyelidlessness almost 11 years@thesystem, that's an odd concern for a method of
Array.prototype
and ani
that is numeric and bound by0
andthis.length
. I think we can safely assume thati
is a property ofthis
, given those characteristics. I suppose it could be an issue if you callArray.prototype.indexOf.call(someArbitraryObjectWithALengthProperty)
, but that would be true of the native method as well. -
eyelidlessness almost 11 years@wilsjd, I have been meaning to update this for some time, to warn against patching prototypes.
-
Stephen Paul almost 11 years'inArray' implies that a boolean will be returned indicating whether the element could be found in the array. Therefore users may feel tempted to use the expression: if ($.inArray('myval', myarray)) {...} This will evaluate to true if 'myval' is NOT in myarray. Furthermore, it will evaluate to false if myval's index is 0.
-
Enrico over 10 yearsvar i = -1, index; Can anyone explain this part? (it returns undefined if the needle is not found in the array) testing on IE8, works fine for firefox
-
ChaseMoskal about 10 yearsThe non-booleanness of
$.inArray
's return definitely feels like a mistake on jQuery's part. Surely, it ought to be renamed to$.indexOf
, if that's the function it's polyfilling? -
romu almost 10 yearsHe wants to find a value in an array, not an index. So this won't do the job, even if it is simple. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
-
Sulthan Allaudeen almost 10 yearsPlease give the explanation to your code. Code only answers are not appreciated
-
deeban almost 10 yearsThis program checks whether the given element is found or not. Id text1 represents id of textbox and searchele represents element to be searched (got fron user); if you want index, use i value.
-
Sulthan Allaudeen almost 10 yearsPlease update it in your answer.
-
gtramontina almost 10 yearsHow about this:
~array.indexOf(value)
-- It'll be truthy if the value exists and falsy otherwhise. So you could do something like:if (~array.indexOf(value)) { console.log('Found it!'); }
-
eyelidlessness almost 10 years@gtramontina, that is very "clever" but confusing to anyone who doesn't know what it does. In order to make it maintainable, you'd overcome your savings in code characters by documenting it with a comment.
-
gtramontina almost 10 years@eyelidlessness I'd rather document it with tests.
-
eyelidlessness almost 10 years@gtramontina, but if anyone else has to read your code, it will be confusing. If not, do whatever you want... but then that calls into question advocating it on a Q&A site.
-
mhenry1384 over 9 years@gtramontina Why would you do a bitwise not (~) rather than a logical not (!)? I guess in this case the end result is the same, but as the next person reading your code, I would spend a few minutes puzzling on that one, as I just did.
-
gtramontina over 9 yearsA logical not (
!
) on its own – i.e.if (!array.indexOf(value))
– would fail the case where the element exists on the first position (0
), as 0 is falsy. -
donohoe over 9 yearsWorks, but requires the jQuery framework. Not ideal if you're not using it otherwise.
-
Nathan Goings almost 9 yearsI'm tempted to post this answer across several javascript questions concerning multiple variable values or arrays. The polyfill from MDN is nice.
-
Jason Cramer almost 9 yearsI really like that you can do this which is essentially the same thing as the jQuery answer above, but without jQuery - plus you can simplify it as Kenneth pointed out, although I couldn't make that work in the console.
-
Dark Star1 over 8 yearsIt's very easy to suggest that someone uses a JQuery method for everything javascript, but as the original question was for a javascript solution, then one should be provided in that manner
-
Doug S over 8 years
indexOf
does not work in <IE9. -
Trevor over 8 yearsDoes not work with
NaN
-
Trevor over 8 yearsDoesn't work for
NaN
-
Trevor over 8 yearsDoes not work for
NaN
-
Trevor over 8 yearsThis solution seems very fragile and prone to error in all but the most narrow cases. Imagine, for example, using this array:
var arr = ["Smith, Reed", "Jackson, Frank"]; arr.contains(searchTerm);
Image that some user accidentally typed"Reed,Jackson"
instead of"Reed, Jackson"
in some text field that searched through this array. This algorithm would return a false positive and the user would think thatReed, Jackson
actually existed when it doesn't. Cases like this are why this algorithm is much more prone to bugs. -
eyelidlessness over 8 years@threed, that's a good catch, but I'm a little stumped about how best to fix it for SO users. I briefly edited the non-native implementation to handle
NaN
, then checked it in CodePen; I realized that the nativeArray.prototype.indexOf
method (at least in Chrome) also doesn't supportNaN
. So on the one hand, the behavior is technically incorrect, but on the other hand it has parity with what the browser provides. I know how I'd solve it in my own projects (a wrapper function, completely sidestepping the native implementation forNaN
), but I'm cautious about misdirecting SO users. -
eyelidlessness over 8 years@threed, thinking more on this, I realize the actual question is not about
indexOf
, that was just an implementation detail. I'll more thoroughly update the answer. -
Trevor over 8 yearsGood call. I recommend taking a look at the MDN polyfill for the Array.includes method.
-
eyelidlessness over 8 years@threed, I took a look at the MDN page, and I honestly found it hard to read. That said, I've updated my answer to handle
NaN
(and included the CodePen) -
ncabral over 8 years@threed, you don't have to include the whole library. Partial functionality can be included with require('lodash/collections/contains').
-
doubleDown about 8 yearsI like how Kenneth J's comment has more upvotes than the answer. But good stuff - I've used indexOf() for strings, but I didn't know you could use it for arrays in general.
-
cgatian about 8 yearsI was actually thinking about going this route, but it still has to transverse the entire array even when a result is found.
-
Chris Schmitz about 8 years@cgatian that's a good point. It's def something to keep in mind when picking which method to use. You could potentially wrap the reduce statement in a
try
catch
block and throw an exception once you've found the value, but if you do that I think you lose some of the simplicity that the functional approach gives you. -
shadowhorst about 8 yearsFYI: With lodash 4 it's now
_.includes()
instead of_.contains()
. -
Zychoo almost 8 years
return ~arrValues.indexOf('Sam')
will returnfalse
if element does not exist in array -
Lukas Liesis almost 8 yearsthanks for this! Babel polyfils it nicely :-) I remember 2 years ago jQuery was in any project and nowadays it's Babel :) big win for JavaScript community! There's table of what's available of ES7 already on many platforms including babel pollyfils kangax.github.io/compat-table/es2016plus
-
Afsal KK over 7 yearsvar numbers = [0,1,2,3,4,5,6,7,8,9]; return jQuery.inArray( parseInt(e.key), numbers )!=-1;
-
nikk wong over 7 yearsIE support can matter if you're targeting certain countries where users use dilapidated hardware.
-
Shahar over 7 yearsAlso worth mentioning that $.inArray('0', ['0', '1', '2']) will return 0, which should be true, but inside and if it evaluates to false.
-
Udara Seneviratne about 7 years[1, 2, 3].includes(2); Array.includes(val) is available since year 2016
-
anneb about 7 yearshelper libraries may seem convenient but tend to change (too) often, see comment above "lodash 4 '.contains()' is now '.includes()'"
-
ncabral about 7 years@anneb that could be said about any library. that's why you have semver and dependency management.
-
Sebastian Mach about 7 years@SujayPhadke: Because money. sitepoint.com/browser-trends-january-2015-ie8-usage-triples . Depending on niche and target market, the percentage may vary.
-
Sujay Phadke about 7 years@SebastianMach and if all web devs just took a stand saying no... users will be forced to change. and helps companies save money since they don't have to hire IE developers
-
Sebastian Mach about 7 years@SujayPhadke: Unfortunately, that's an Utopia. For any group of people beyond a critical mass, there will never be perfect agreement.
-
Sujay Phadke about 7 years@SebastianMach agreed. But it has happened before, (recent past). Adobe Flash had a huge critical mass, no one can argue that. It took one company to make a logical tech argument to end flash on the web and bring in standards.
-
Sebastian Mach about 7 years@SujayPhadke: True. It was the company holding the de facto monopoly. Microsoft would be required to destroy IE. However, would they deploy such a mandatory uninstallation, there would be users outcrying (at least I bet so).
-
Anshul about 7 years@SujayPhadke Or the developers who make a stand will get fired and the company will hire new devs who can comply with IE. It goes both ways.
-
Fusseldieb almost 6 years"Doesn't work on <IE9" - users shall upgrade their browsers, it's not that hard. Even Microsoft buried their IE browser, because it was so bad (and nobody really liked it).
-
Admin almost 6 years@DougS indexOf works in node.js, so awesome!
-
Martin James almost 6 yearsYou could use a bitwise operator like
if (!~$.inArray(0, [13, 27, 35, 36, 37, 38, 39, 40])) {}
. The tilde (~) transforms -1 to 0 and 0 is equal to false in Javascript. -
fwiw almost 6 yearsIn Lodash versions prior to 2.x _.include() is an alias for _.contains() and there is no _.includes() defined. As of ver. 3.x, _.include() and _.contains() are both aliases for _includes(). But as of ver. 4.x, there is only _.includes() and no more other aliases.
-
Zach Smith over 5 yearsI once wanted to retrieve values from an object via a case-insensitive index look up. lodash doesn't (didn't at the time at least) have a performant way of doing this. So you can't just assume that because it's a popular library that it will always be performant for your specific requirement
-
ncabral over 5 years@ZachSmith I understand. But emphasis on the "specific requirement" there. I only mentioned this as an "almost always" applicable answer. And case-insensitive index lookups are the exception to the norm - hence, lodash isn't optimised for it.
-
Vijay Kumar Kanta about 5 yearsWorks fine for latest browsers and also string literals. Superb!
-
Danish almost 5 yearsnice way to use actually set.