Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    New to the CF scene
    Join Date
    Mar 2013
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Search Array for multiple values?

    Hello all,

    I'm new to this forum.

    Is it possible to search an array for multiple values?

    For example, I have an array that contains the following:

    PHP Code:
    var myCars = new Array("Ford""Chevy""GMC""Buick""Dodge""Jeep"); 
    The values can change or contain additional values.

    Is there a method to loop through the array to check if it contains "Ford" or "Chevy"?
    PHP Code:
    myCars.indexOf('Ford' || 'Chevy') > -

  • #2
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    What result do you expect? This will simply return a boolean value, but you can easily adapt it to return, for example, the index of the first occurence:

    Code:
    Array.prototype.containsOneOf = function (needles) {
        for( var i = 0; i < needles.length; i++ ) {
            if( this.indexOf( needles[i] ) > -1 ) {
                return true;
            }
        }
        
        return false;
    }
    Edit: Here's an example on how to use it:

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");  
    
    console.log( myCars.containsOneOf( ['Ford', 'Chevy'] ) ); // true
    console.log( myCars.containsOneOf( ['Banana', 'Chevy'] ) ); // true
    console.log( myCars.containsOneOf( ['Ford', 'Banana'] ) ); // true
    console.log( myCars.containsOneOf( ['Foo', 'Bar'] ) ); // false
    Last edited by Airblader; 03-18-2013 at 08:55 PM.

  • #3
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,550
    Thanks
    78
    Thanked 4,382 Times in 4,347 Posts
    No built-in method, but it is so incredibly trivial to create your own that you shouldn't care.
    Code:
    function arraySearch( ary, find )
    {
        for ( var a = 0; a < ary.length; ++a )
        {
            for ( var f = 0; f < find.length; ++f )
            {
                if ( ary[a] == find[f] ) return ary[a];
            }
        }
        return null;
    }
    Not the cleverest code in the world but pretty trivial to create. Only finds the first match. You pass it two arrays: The one to search and one that contains the things to find.

    Or, if you are into regular expressions:
    Code:
    function arraySearch( ary, find )
    {
        if ( ! ( find instanceof Array ) ) { find = [ find ]; }
        find = new RegExp( find.join("|"), "i" );
        results = [];
        for ( var a = 0; a < ary.length; ++a )
        {
            if ( find.test( ary[a] ) ) results.push( ary[a] );
        }
        return results;
    }
    This one is kind of fun, because you could call it via
    Code:
        arraySearch( myCars, ["Ford","Dodge"] ) // passing an array of what to find
        arraySearch( myCars, "Ford" ) // passing a single string to find
        arraySearch( myCars, "Ford|Buick" ) // passing an "or"ed regular expression
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,550
    Thanks
    78
    Thanked 4,382 Times in 4,347 Posts
    or, of course, convert either of those into Prototype methods, as Airblader did.
    Code:
    Array.prototype.containsAny = function( find )
    {
        if ( ! ( find instanceof Array ) ) { find = [ find ]; }
        find = new RegExp( find.join("|"), "i" );
        results = [];
        for ( var a = 0; a < this.length; ++a )
        {
            if ( find.test( this[a] ) ) results.push( this[a] );
        }
        return results;
    }
    
    var myCars = ["Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep"];
    document.write( myCars.containsAny( ["Ford","Dodge"] ) );
    document.write("<hr>");
    document.write( myCars.containsAny( "Ford|Buick" ) );
    I think I like this regexp-based method for its flexibility.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #5
    Regular Coder
    Join Date
    Jan 2013
    Location
    Germany
    Posts
    578
    Thanks
    4
    Thanked 77 Times in 77 Posts
    Here are three functions, each one returning something different. None of them utilizes Old Pedant's RegEx version, though:

    Code:
    /**
      *  Returns true if at least one of the needles is contained.
      */
    Array.prototype.containsOneOf = function (needles) {
        if( !( needles instanceof Array ) ) {
            needles = [needles];
        }
        
        for( var i = 0; i < needles.length; i++ ) {
            if( this.indexOf( needles[i] ) > -1 ) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
      *  Returns an array containing the index of the corresponding needles
      */
    Array.prototype.indexOfMultiple = function (needles) {
        if( !( needles instanceof Array ) ) {
            needles = [needles];
        }
        
        var indices = [];
        for( var i = 0; i < needles.length; i++ ) {
            indices.push( this.indexOf( needles[i] ) );
        }
        
        return indices;
    }
    
    /**
      *  Returns an array consisting only of elements contained both in 'this' and needles.
      */
    Array.prototype.filterContainedElements = function (needles) {
        if( !( needles instanceof Array ) ) {
            needles = [needles];
        }
        
        var contained = [];
        for( var i = 0; i < needles.length; i++ ) {
            if( this.indexOf( needles[i] ) > -1 ) {
                contained.push( needles[i] );
            }
        }
        
        return contained;
    }

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,550
    Thanks
    78
    Thanked 4,382 Times in 4,347 Posts
    Heh! If he wasn't confused before, he will be now! Teach him not to ask for something specific.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    It's simpler and faster to use built-in methods than to hand-code loopy utils...

    the simplest way is to use RegExp instead of looping (which i try to avoid):

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");
    
    myCars.some(/./.test, /Ford|Chevy/) // true if myCars contains "Chevy" or "Ford" (anywhere in array)

    EDIT
    you can easily add some safety to that using boundries (now that the simple method is demonstrated)

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");
    myCars.some(/./.test, /\bFord\b|\bChevy\b/) // true if myCars contains "Chevy" or "Ford" (whole element match only)
    and you can expand that to accept an array of other choices instead of a hand-coded regexp (still without a loop or custom function) :

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");
    var myList=["Saab", "BMW", "Chevy"];
    
    myCars.some(/./.test, new RegExp( "\\b("+myList.join("|")+")\\b"   ));  // true if myCars contains "Saab", "BMW", or  "Chevy"(whole element match only)
    bonus:

    using the last syntax, it's super easy to make sure that EVERY item on a sub-list is on the main list (just in case anyone needs to know how to do that) :

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");
    var myList=["Dodge", "Ford", "Chevy"];
    myList.every(/./.test, new RegExp( "\\b("+myCars.join("|")+")\\b"   ));   // true

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");
    var myList=["Dodge", "Ford", "BMW"];
    myList.every(/./.test, new RegExp( "\\b("+myCars.join("|")+")\\b"   ));   // false
    Last edited by rnd me; 03-18-2013 at 11:05 PM.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • Users who have thanked rnd me for this post:

    Airblader (03-19-2013)

  • #8
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,550
    Thanks
    78
    Thanked 4,382 Times in 4,347 Posts
    Yes, I even considered doing it via a simple join on the array. And if all you want is a test for existence, any of those work fine. If you want to know *what* the matches are, though...

    Of course, some and every don't exist in all browsers, but I know that doesn't bother you, which is fine. Just not something I will (yet) use. (And, yes, I know I could add them to the Array prototype, but then I'm back to doing a loop in JS code.)
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #9
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,349
    Thanks
    11
    Thanked 589 Times in 570 Posts
    Quote Originally Posted by Old Pedant View Post
    Yes, I even considered doing it via a simple join on the array. And if all you want is a test for existence, any of those work fine. If you want to know *what* the matches are, though...
    we can still use an array; "".match() is generic:

    Code:
    var myCars = new Array("Ford", "Chevy", "GMC", "Buick", "Dodge", "Jeep");
    
    "".match.call( myCars, /Ford|Chevy/g )
    this avoids the old-school IE problems associated with not having [].some() built-in...
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •