834

What is the best way to find if an object is in an array?

This is the best way I know:

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

console.log(include([1, 2, 3, 4], 3)); // true
console.log(include([1, 2, 3, 4], 6)); // undefined
dota2pro
  • 7,220
  • 7
  • 44
  • 79
zimbatm
  • 9,348
  • 4
  • 20
  • 11
  • See: http://stackoverflow.com/a/25765186/1320932 – dr.dimitru Sep 10 '14 at 12:18
  • 5
    2 things: 1.) 'include' is a really bad name for a function that does not modify the state of anything. It's especially bad for a function that simply returns a boolean. 2.) You need to add "return(false);" before the end of the function. – Aquarelle May 12 '15 at 00:57
  • 3
    as of ECMAScript 2016, you can use Array.prototype.includes function: myArray.includes(3); // true – mhd Jun 15 '16 at 13:25
  • 3
    In ES6 you can do something like arr.find(lamda function) , example: [1, 2, 3,4,5].find(x => x == 3). if element is found it is returned else undefined is returned – ALLSYED Jul 29 '16 at 10:26
  • arr.some(element => element === obj); some is the bestway because when it finds an item and then break the loop. – Cenk Çetinkaya Jan 09 '18 at 11:58

8 Answers8

766

As of ECMAScript 2016 you can use includes()

arr.includes(obj);

If you want to support IE or other older browsers:

function include(arr,obj) {
    return (arr.indexOf(obj) != -1);
}

EDIT: This will not work on IE6, 7 or 8 though. The best workaround is to define it yourself if it's not present:

  1. Mozilla's (ECMA-262) version:

       if (!Array.prototype.indexOf)
       {
    
            Array.prototype.indexOf = function(searchElement /*, fromIndex */)
    
         {
    
    
         "use strict";
    
         if (this === void 0 || 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 > 0)
         {
           n = Number(arguments[1]);
           if (n !== n)
             n = 0;
           else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
             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;
       };
    
     }
    
  2. Daniel James's version:

     if (!Array.prototype.indexOf) {
       Array.prototype.indexOf = function (obj, fromIndex) {
         if (fromIndex == null) {
             fromIndex = 0;
         } else if (fromIndex < 0) {
             fromIndex = Math.max(0, this.length + fromIndex);
         }
         for (var i = fromIndex, j = this.length; i < j; i++) {
             if (this[i] === obj)
                 return i;
         }
         return -1;
       };
     }
    
  3. roosteronacid's version:

     Array.prototype.hasObject = (
       !Array.indexOf ? function (o)
       {
         var l = this.length + 1;
         while (l -= 1)
         {
             if (this[l - 1] === o)
             {
                 return true;
             }
         }
         return false;
       } : function (o)
       {
         return (this.indexOf(o) !== -1);
       }
     );
    
user229044
  • 232,980
  • 40
  • 330
  • 338
Vinko Vrsalovic
  • 330,807
  • 53
  • 334
  • 373
  • I'm curious as to why your version of the Mozilla function is so different from the website you're linking to. Did you modify it yourself or is it just an old version or something? – Justin G Mar 11 '14 at 01:16
  • 6
    @Shenjoku: "answered Sep 27 '08 at 15:45" – Vinko Vrsalovic Mar 11 '14 at 05:49
  • Well, there's my answer haha. I can't tell if there's an older version just by looking at the mozilla website so I wasn't sure. Not that it matters, just a curiosity. In any case this was still helpful so you get an upvote ;) – Justin G Mar 13 '14 at 02:24
  • @Vinko Vrsalovic Yes, it is a good solution, but you should hide embedded implementation indexOf() function which returns -1 with ~ operator: function include(arr,obj) { return !!(~arr.indexOf(obj)) ; } – KRRySS Aug 02 '17 at 11:53
  • but, since when is indexOf compatible with IE, because I found it is compatible with IE https://www.w3schools.com/jsref/jsref_indexof.asp – sgelves Aug 24 '17 at 13:18
  • @VinkoVrsalovic how do I modify this function function include(arr,obj) { return (arr.indexOf(obj) != -1); } To return true or false when passing it multiple values like maybe two strings? :D – Rich Cuer Feb 19 '20 at 01:03
  • Another option is to use .find() more information here: https://stackoverflow.com/a/62305136/19276480 – Angus Feb 21 '23 at 14:08
210

If you are using jQuery:

$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);

For more information: http://api.jquery.com/jQuery.inArray/

Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
Germán Rodríguez
  • 4,284
  • 1
  • 19
  • 19
  • 11
    Note that "inArray" is a misnomer, because it doesn't return boolean value - it returns index of first element found. So if you are checking if element exists you should use `if (-1 != $.inArray(...)) ...`. – johndodo Feb 10 '17 at 07:51
  • 5
    Helpful, but I don't think it's an appropriate answer here. The question is tagged "javascript" indicating "vanilla" in my opinion. :) – iMe Nov 01 '17 at 14:37
34

First, implement indexOf in JavaScript for browsers that don't already have it. For example, see Erik Arvidsson's array extras (also, the associated blog post). And then you can use indexOf without worrying about browser support. Here's a slightly optimised version of his indexOf implementation:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (obj, fromIndex) {
        if (fromIndex == null) {
            fromIndex = 0;
        } else if (fromIndex < 0) {
            fromIndex = Math.max(0, this.length + fromIndex);
        }
        for (var i = fromIndex, j = this.length; i < j; i++) {
            if (this[i] === obj)
                return i;
        }
        return -1;
    };
}

It's changed to store the length so that it doesn't need to look it up every iteration. But the difference isn't huge. A less general purpose function might be faster:

var include = Array.prototype.indexOf ?
    function(arr, obj) { return arr.indexOf(obj) !== -1; } :
    function(arr, obj) {
        for(var i = -1, j = arr.length; ++i < j;)
            if(arr[i] === obj) return true;
        return false;
    };

I prefer using the standard function and leaving this sort of micro-optimization for when it's really needed. But if you're keen on micro-optimization I adapted the benchmarks that roosterononacid linked to in the comments, to benchmark searching in arrays. They're pretty crude though, a full investigation would test arrays with different types, different lengths and finding objects that occur in different places.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Daniel James
  • 3,899
  • 22
  • 30
  • The code examples you are linking to are slow on large arrays. See the comments in my implementation example of a hasItem() function. – cllpse Sep 27 '08 at 23:06
  • Take a look at these benchmarks: http://blogs.sun.com/greimer/resource/loop-test.htm For-loops are slow. But I guess the arrays used in the benchmarks are pretty huge :) – cllpse Sep 28 '08 at 11:28
  • 1
    http://blogs.sun.com/greimer/resource/loop-test.html – cllpse Sep 28 '08 at 11:37
  • I agree. I'm also quite pragmatic. But in the case of optimizing the very basics of the language, I think it's good design to implement functionality as performance-effective as possible. – cllpse Sep 28 '08 at 15:14
  • use mozilla Array.indexOf polyfill: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Polyfill – user1742529 Feb 22 '20 at 03:55
13

If the array is unsorted, there isn't really a better way (aside from using the above-mentioned indexOf, which I think amounts to the same thing). If the array is sorted, you can do a binary search, which works like this:

  1. Pick the middle element of the array.
  2. Is the element you're looking for bigger than the element you picked? If so, you've eliminated the bottom half of the array. If it isn't, you've eliminated the top half.
  3. Pick the middle element of the remaining half of the array, and continue as in step 2, eliminating halves of the remaining array. Eventually you'll either find your element or have no array left to look through.

Binary search runs in time proportional to the logarithm of the length of the array, so it can be much faster than looking at each individual element.

assortedslog
  • 141
  • 4
10

[ ].has(obj)

assuming .indexOf() is implemented

Object.defineProperty( Array.prototype,'has',
{
    value:function(o, flag){
    if (flag === undefined) {
        return this.indexOf(o) !== -1;
    } else {   // only for raw js object
        for(var v in this) {
            if( JSON.stringify(this[v]) === JSON.stringify(o)) return true;
        }
        return false;                       
    },
    // writable:false,
    // enumerable:false
})

!!! do not make Array.prototype.has=function(){... because you'll add an enumerable element in every array and js is broken.

//use like          
[22 ,'a', {prop:'x'}].has(12) // false
["a","b"].has("a") //  true

[1,{a:1}].has({a:1},1) // true
[1,{a:1}].has({a:1}) // false

the use of 2nd arg (flag) forces comparation by value instead of reference

comparing raw objects

[o1].has(o2,true) // true if every level value is same
bortunac
  • 4,642
  • 1
  • 32
  • 21
8

It depends on your purpose. If you program for the Web, avoid indexOf, it isn't supported by Internet Explorer 6 (lot of them still used!), or do conditional use:

if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);

indexOf is probably coded in native code, so it is faster than anything you can do in JavaScript (except binary search/dichotomy if the array is appropriate). Note: it is a question of taste, but I would do a return false; at the end of your routine, to return a true Boolean...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PhiLho
  • 40,535
  • 6
  • 96
  • 134
  • 1
    ha...I shrill to think there's still an IE6 client out there at this point... – beauXjames Aug 15 '14 at 16:25
  • shouldn't there be a "as of 2008" like in wikipedia page so that people know this statement is certainly outdated – allan.simon May 05 '16 at 14:20
  • 3
    @allan.simon Look at my icon (and stats) at the bottom of my answer. Just above, there is "answered Sep 27 '08 at 16:28". It is called a date, and people used to Stack Overflow look at these dates to take answers with a grain of salt... That said, my local public library still has IE6 installed on their computers! (but somebody installed Chrome, fortunately!) – PhiLho May 05 '16 at 22:36
6

Here's some meta-knowledge for you - if you want to know what you can do with an Array, check the documentation - here's the Array page for Mozilla

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

There you'll see reference to indexOf, added in Javascript 1.6

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
5

A robust way to check if an object is an array in javascript is detailed here:

Here are two functions from the xa.js framework which I attach to a utils = {} ‘container’. These should help you properly detect arrays.

var utils = {};

/**
 * utils.isArray
 *
 * Best guess if object is an array.
 */
utils.isArray = function(obj) {
     // do an instanceof check first
     if (obj instanceof Array) {
         return true;
     }
     // then check for obvious falses
     if (typeof obj !== 'object') {
         return false;
     }
     if (utils.type(obj) === 'array') {
         return true;
     }
     return false;
 };

/**
 * utils.type
 *
 * Attempt to ascertain actual object type.
 */
utils.type = function(obj) {
    if (obj === null || typeof obj === 'undefined') {
        return String (obj);
    }
    return Object.prototype.toString.call(obj)
        .replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase();
};

If you then want to check if an object is in an array, I would also include this code:

/**
 * Adding hasOwnProperty method if needed.
 */
if (typeof Object.prototype.hasOwnProperty !== 'function') {
    Object.prototype.hasOwnProperty = function (prop) {
        var type = utils.type(this);
        type = type.charAt(0).toUpperCase() + type.substr(1);
        return this[prop] !== undefined
            && this[prop] !== window[type].prototype[prop];
    };
}

And finally this in_array function:

function in_array (needle, haystack, strict) {
    var key;

    if (strict) {
        for (key in haystack) {
            if (!haystack.hasOwnProperty[key]) continue;

            if (haystack[key] === needle) {
                return true;
            }
        }
    } else {
        for (key in haystack) {
            if (!haystack.hasOwnProperty[key]) continue;

            if (haystack[key] == needle) {
                return true;
            }
        }
    }

    return false;
}
Aaria Carter-Weir
  • 1,639
  • 12
  • 17
  • While this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. Also, when you copy/paste the same link-only answer to several very old questions at once, it just looks like spam. – Bill the Lizard Aug 18 '11 at 12:48
  • Sorry Bill, I really didn't mean it to seem like spam and was just trying to update a few of the old questions about this topic too. I've edited the post here to include the actual answer instead of linking off. – Aaria Carter-Weir Aug 22 '11 at 07:37
  • @Bill, actually re-reading the question, this doesn't even answer it at all. I must have made a mistake. – Aaria Carter-Weir Aug 22 '11 at 07:40