Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript filter array by multiple strings

I'm trying to filter an Array named products which is filled with one string per product.

var products = [
    'canadian black angus beef fresh',
    'canadian black angus beef frozen',
    'american black angus beef frozen'
];

The search starts by splitting an form input element by spaces in an array named keywords which contains an variable length of strings.

var keywords = ['angus', 'fresh'];

Actually I'm for-looping the product_array and make an 2nd (inner) for-loop for the keyword_array. Till now its all fine.

here is my shorten code which shows the issue:

function test() {
    
    var products = [
        'canadian black angus beef fresh',
        'canadian black angus beef frozen',
        'american black angus beef frozen'
    ];
    
    var keywords = ['angus', 'fresh'];
    var hits = [];
    
    for (var i = 0; i < products.length; i++) {
        
        for (var j = 0; j < keywords.length; j++) {
            
            if (products[i].indexOf(keywords[j]) != -1) {
                
                /*
                a if case for looped '&&' operator 
                would be great - or something like that
                looped because of the variable length of keywords
                */
                hits.push(products[i]);
            }
        }
    }
    
    console.log(hits);
    /* 
    all products :/ - because all product matches with 'angus'
    but I'm searching for an product that contains 'angus' && 'fresh'
    */
}

How can I fix this?

like image 514
Tarek Haddad Avatar asked Sep 10 '25 06:09

Tarek Haddad


2 Answers

First of all, you should take a look at the .filter() function. It iterates through an array, and returns the items you want, based on a true/false return of the conditions you set.

MDN's Docs on Array.prototype.filter()

Now, to be sure that both keywords exists, you can use some flag to indicate whether it does or doesn't:

var hits = products.filter(function(item) {
    var valid = true;
    for (var i = 0; i < keywords.length; i++) {
        if (item.indexOf(keywords[i]) === -1) {
            valid = false;
        }
    }

    return valid;
});
like image 126
LcSalazar Avatar answered Sep 12 '25 18:09

LcSalazar


Just put a flag that check if you have all keywords :

var containsAll;

for (var i = 0; i < products.length; i++) {

    // Initialize flag -> guess that this product is correct
    containsAll = true;
    for (var j = 0; j < keywords.length; j++) {
        if (products[i].indexOf(keywords[j]) === -1) {
            // This keyword is not matched -> incorrect product
            containsAll = false;
            break;
        }
    }

    // All products has been matched
    if (containsAll) hits.push(products[i]);
}

See this fiddle : http://jsfiddle.net/eoz1y8n4/

like image 20
Samuel Caillerie Avatar answered Sep 12 '25 19:09

Samuel Caillerie