tags:

views:

5034

answers:

4

Is there anyway in Javascript to compare values from one array and see if it is in another array? Similar to PHP's in_array function?

+10  A: 

No, it doesn't have one. For this reason most popular libraries come with one in their utility packages. Check out jQuery's inArray and Prototype's Array.indexOf for examples.

jQuery's implementation of it is as simple as you might expect:

function inArray(needle, haystack) {
    var length = haystack.length;
    for(var i = 0; i < length; i++) {
        if(haystack[i] == needle) return true;
    }
    return false;
}

If are you dealing with a sane amount of array elements the above will do the trick nicely.

EDIT: Whoops. I didn't even notice you wanted to see if an array was inside another. According to the PHP docs this is the expected behavior of PHP's in_array:

$a = array(array('p', 'h'), array('p', 'r'), 'o');

if (in_array(array('p', 'h'), $a)) {
    echo "'ph' was found\n";
}

if (in_array(array('f', 'i'), $a)) {
    echo "'fi' was found\n";
}

if (in_array('o', $a)) {
    echo "'o' was found\n";
}

// output:
// 'ph' was found
// 'o' was found

The code posted by Chris and Alex does not follow this behavior. Alex's is the official version of Prototype's indexOf, and Chris's is more like PHP's array_intersect. This does what you want:

function arrayCompare(a1, a2) {
    if (a1.length != a2.length) return false;
    var length = a2.length;
    for (var i = 0; i < length; i++) {
        if (a1[i] !== a2[i]) return false;
    }
    return true;
}

function inArray(needle, haystack) {
    var length = haystack.length;
    for(var i = 0; i < length; i++) {
        if(typeof haystack[i] == 'object') {
            if(arrayCompare(haystack[i], needle)) return true;
        } else {
            if(haystack[i] == needle) return true;
        }
    }
    return false;
}

And this my test of the above on it:

var a = [['p','h'],['p','r'],'o'];
if(inArray(['p','h'], a)) {
    alert('ph was found');
}
if(inArray(['f','i'], a)) {
    alert('fi was found');
}
if(inArray('o', a)) {
    alert('o was found');
}  
// results:
// alerts 'ph' was found
// alerts 'o' was found

Note that I intentionally did not extend the Array prototype as it is generally a bad idea to do so.

Paolo Bergantino
+2  A: 

There is not a native function for this.

The code here is good.

artlung
+2  A: 

If you only want to check if a single value is in an array, then Paolo's code will do the job. If you want to check which values are common to both arrays, then you'll want something like this (using Paolo's inArray function):

function arrayIntersect(a, b) {
    var intersection = [];

    for(var i = 0; i < a.length; i++) {
        if(inArray(b, a[i]))
            intersection.push(a[i]);
    }

    return intersection;
}

This wil return an array of values that are in both a and b. (Mathematically, this is an intersection of the two arrays.)

EDIT: See Paolo's Edited Code for the solution to your problem. :)

Chris Doble
Although this is nice, it is not really what the OP asked for; it doesn't replicate the functionality of PHP's in_array.
Paolo Bergantino
+3  A: 

Array.indexOf is implemented JavaScript 1.6, but it is not going to be of much use to you in the majority of circumstances. Thankfully the chaps over at Mozilla have done all the hard work for, and provided you with this for compatibility:

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;
  };
}

There are even some handy usage snippets for your scripting pleasure.

Alex Barrett
This is a nicer/safer/better implementation of the links/code posted here already; the specs don't call for checking for arrays inside the haystack, and that's what the OP wants.
Paolo Bergantino
Incidentally, what's the purpose of `this.length >>> 0`? Is that a conversion to a Number type?
harto
`Array.indexOf` is now standardised by ECMAScript Fifth Edition so should be considered the proper ‘native’ way of doing it. You will still need to sniff and provide this backup for older browser for a long time, though. @harto: yes, it converts `this.length` to a Number that can be represented as a 32-bit unsigned integer. A native `Array` can only have a length that already complies with this, but the spec states that you can call `Array.prototype` methods on native-JS objects that are not `Array`. This and the other pedantic argument checking stuff is to guarantee absolute spec-compliance.
bobince