2

How can I check whether a particular element is inside an array? I don't want to manually write a loop for this; instead I want to use a JavaScript built-in function, maybe something equivalent to

new Array(0,1,2,3,6,9,12,15,18).Contains(5)  //return false
new Array(0,1,2,3,6,9,12,15,18).Contains(1)   //return true
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Graviton
  • 81,782
  • 146
  • 424
  • 602

6 Answers6

12

The Array object does have an indexOf function, that will return -1 if the object does not exist. However, IE does not support this function.

Regardless, how do you think it is going to locate the item under the scenes? It will have to loop! Just because there's a built-in function does not mean that it is magical.

Josh Stodola
  • 81,538
  • 47
  • 180
  • 227
  • 5
    +1 for mentioning that it uses a loop internally. I think a lot of people don't get that, especially people coming from Ruby, in my experience. :) – Sasha Chedygov Jul 03 '09 at 04:52
  • Well, there is a loop, but loops in Ruby, for example are going to be faster if they're native than in they're written in Ruby itself. For example, that particular check would be coded in C, running much more quickly than a loop written in Ruby, so while native methods might not be magical, they're definitely faster. The same is true for JavaScript's built-in methods. – Andrew Noyes Jul 03 '09 at 04:57
  • 3
    @Andrew Noyes: Yeah, but when someone says "I want to do this without using a loop", that's technically impossible. ;) – Sasha Chedygov Jul 03 '09 at 05:04
  • The fact that hand-written loops would have to be interpreted is the only reason that they would be slower. – Josh Stodola Jul 03 '09 at 05:05
4

You could also write an extension method, as explained in this thread.

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
Community
  • 1
  • 1
Shane Fulmer
  • 7,510
  • 6
  • 35
  • 43
  • 1
    You could utilize indexOf here as well, at least for the implementations that support it! – Josh Stodola Jul 03 '09 at 04:49
  • BTW, the firefox algorithm for internally locating an item in an array (indexOf) is available at the link in my answer. I'm certain it will be faster than this while loop. – Josh Stodola Jul 03 '09 at 04:55
  • @Josh: I doubt it's any faster. There are a lot of checks to make sure the right arguments are passed, etc, so I don't see why it would be faster. @DeadHead: Why is it not portable? The source code is right here: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf#Compatibility – Sasha Chedygov Jul 03 '09 at 05:56
2

As @Josh Stodola said, the indexOf function is what you need, but this function was introduced on JavaScript 1.6, for compatibility you can use this implementation from the Mozilla team, is exactly the one used in Firefox and SpiderMonkey:

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}

Source: MDC

Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
1

There is no such method in javascript.

Some library (e.g. jquery) have similar method, but they use loops internally.

J-16 SDiZ
  • 26,473
  • 4
  • 65
  • 84
1

Looks like a job for jQuery.inArray

inArray: function( elem, array ) {
    for ( var i = 0, length = array.length; i < length; i++ )
    // Use === because on IE, window == document
        if ( array[ i ] === elem )
            return i;

    return -1;
}
Josh Stodola
  • 81,538
  • 47
  • 180
  • 227
Slim
  • 5,635
  • 7
  • 31
  • 30
1

Ah, there is a way not to loop and it is pretty simple, people just do not think outside the box.

Array.prototype.contains = function(){     
    var joined = this.join("-~-");
    var re = new RegExp("(^|-~-)" + arguments[0] + "($|-~-)");   
    return joined.match(re) !== null;
}

var arr = ["a","b","c","d"];   
alert(arr.contains("a"));
alert(arr.contains("b"));
alert(arr.contains("c"));
alert(arr.contains("d"));
alert(arr.contains("e"));

Loop mom, no loops!

epascarello
  • 204,599
  • 20
  • 195
  • 236