views:

307

answers:

6

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

Edit the question to make my intention clearer

A: 

There is no such method in javascript.

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

J-16 SDiZ
+13  A: 

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
+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. :)
musicfreak
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
@Andrew Noyes: Yeah, but when someone says "I want to do this without using a loop", that's technically impossible. ;)
musicfreak
The fact that hand-written loops would have to be interpreted is the only reason that they would be slower.
Josh Stodola
@musicfreak: True. :)
Andrew Noyes
+4  A: 

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
Shane Fulmer
This method also use looping
rahul
Of course it does.
Shane Fulmer
You could utilize indexOf here as well, at least for the implementations that support it!
Josh Stodola
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
Faster, yes, portable, no.
DeadHead
@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
musicfreak
+2  A: 

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

CMS
I already had a link to this, but thanks for posting the code!
Josh Stodola
+1  A: 

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;
}
Slim
Hey, jQuery.inArray use loops in its guts
J-16 SDiZ
I edited this, and added the inArray function directly from the jQuery source, just for reference.
Josh Stodola
+1  A: 

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
the regex has lots of loops internally...
usr
Could be true, but it is not looping in the user written JavaScript code. :)
epascarello
Nice one, Eric! This has to perform terribly, though.
Josh Stodola