Determine whether an array contains a value

1,737,338

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

CodePen validation/usage

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, returning true or false 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().

Share:
1,737,338
Prasad
Author by

Prasad

Updated on November 05, 2020

Comments

  • Prasad
    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
    RaYell almost 15 years
    Note that indexOf on arrays is not implemented in IE, but you can define it yourself
  • Christoph
    Christoph almost 15 years
    you should use a typed comparison with === to be compatible with the native implementation
  • eyelidlessness
    eyelidlessness almost 15 years
    That's redundant.
  • Prasad
    Prasad almost 15 years
    I have tried all the answers given , but still returning false.
  • Prasad
    Prasad almost 15 years
    Finally its worked. its due to improper trim of the comparing value. there was some space in the comparing value
  • rlovtang
    rlovtang almost 15 years
    Maybe, 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
    Greg Bernhardt about 13 years
    Don'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
    Vivian River about 12 years
    What version of IE does this answer refer to?
  • Sahat Yalkabov
    Sahat Yalkabov over 11 years
    Isn't this technique of augmenting built-in types frowned upon?
  • Trevor
    Trevor over 11 years
    Does this work in all browsers? Or do some browsers consider the index of "2" and 2 the same?
  • Eamon Nerbonne
    Eamon Nerbonne over 11 years
    Buggy: [1,2,4].contains([].contains) is true. Also unnecessarily slow due to the same bug. Avoid for..in over arrays.
  • Trevor
    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
    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
    the system about 11 years
    The shim should test if i is a property of this.
  • wilsjd
    wilsjd about 11 years
    Note that in Sharepoint 2010, WebParts can break if you implement an Array.Prototype: labs.steveottenad.com/type-mismatch-on-wpadder-js
  • Jeffz
    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
    eyelidlessness almost 11 years
    @thesystem, that's an odd concern for a method of Array.prototype and an i that is numeric and bound by 0 and this.length. I think we can safely assume that i is a property of this, given those characteristics. I suppose it could be an issue if you call Array.prototype.indexOf.call(someArbitraryObjectWithALengthP‌​roperty), but that would be true of the native method as well.
  • eyelidlessness
    eyelidlessness almost 11 years
    @wilsjd, I have been meaning to update this for some time, to warn against patching prototypes.
  • Stephen Paul
    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
    Enrico over 10 years
    var 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
    ChaseMoskal about 10 years
    The 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
    romu almost 10 years
    He 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
    Sulthan Allaudeen almost 10 years
    Please give the explanation to your code. Code only answers are not appreciated
  • deeban
    deeban almost 10 years
    This 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
    Sulthan Allaudeen almost 10 years
    Please update it in your answer.
  • gtramontina
    gtramontina almost 10 years
    How 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
    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
    gtramontina almost 10 years
    @eyelidlessness I'd rather document it with tests.
  • eyelidlessness
    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
    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
    gtramontina over 9 years
    A 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
    donohoe over 9 years
    Works, but requires the jQuery framework. Not ideal if you're not using it otherwise.
  • Nathan Goings
    Nathan Goings almost 9 years
    I'm tempted to post this answer across several javascript questions concerning multiple variable values or arrays. The polyfill from MDN is nice.
  • Jason Cramer
    Jason Cramer almost 9 years
    I 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
    Dark Star1 over 8 years
    It'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
    Doug S over 8 years
    indexOf does not work in <IE9.
  • Trevor
    Trevor over 8 years
    Does not work with NaN
  • Trevor
    Trevor over 8 years
    Doesn't work for NaN
  • Trevor
    Trevor over 8 years
    Does not work for NaN
  • Trevor
    Trevor over 8 years
    This 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 that Reed, Jackson actually existed when it doesn't. Cases like this are why this algorithm is much more prone to bugs.
  • eyelidlessness
    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 native Array.prototype.indexOf method (at least in Chrome) also doesn't support NaN. 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 for NaN), but I'm cautious about misdirecting SO users.
  • eyelidlessness
    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
    Trevor over 8 years
    Good call. I recommend taking a look at the MDN polyfill for the Array.includes method.
  • eyelidlessness
    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
    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
    doubleDown about 8 years
    I 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
    cgatian about 8 years
    I was actually thinking about going this route, but it still has to transverse the entire array even when a result is found.
  • Chris Schmitz
    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
    shadowhorst about 8 years
    FYI: With lodash 4 it's now _.includes() instead of _.contains().
  • Zychoo
    Zychoo almost 8 years
    return ~arrValues.indexOf('Sam') will return false if element does not exist in array
  • Lukas Liesis
    Lukas Liesis almost 8 years
    thanks 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
    Afsal KK over 7 years
    var numbers = [0,1,2,3,4,5,6,7,8,9]; return jQuery.inArray( parseInt(e.key), numbers )!=-1;
  • nikk wong
    nikk wong over 7 years
    IE support can matter if you're targeting certain countries where users use dilapidated hardware.
  • Shahar
    Shahar over 7 years
    Also 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
    Udara Seneviratne about 7 years
    [1, 2, 3].includes(2); Array.includes(val) is available since year 2016
  • anneb
    anneb about 7 years
    helper libraries may seem convenient but tend to change (too) often, see comment above "lodash 4 '.contains()' is now '.includes()'"
  • ncabral
    ncabral about 7 years
    @anneb that could be said about any library. that's why you have semver and dependency management.
  • Sebastian Mach
    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
    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
    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
    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
    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
    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
    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
    Admin almost 6 years
    @DougS indexOf works in node.js, so awesome!
  • Martin James
    Martin James almost 6 years
    You 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
    fwiw almost 6 years
    In 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
    Zach Smith over 5 years
    I 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
    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
    Vijay Kumar Kanta about 5 years
    Works fine for latest browsers and also string literals. Superb!
  • Danish
    Danish almost 5 years
    nice way to use actually set.