简体   繁体   中英

Javascript string in array or a part

I have a Javascript array with multiple values:

var filterClasses = ['col-sm-12', 'hidden-xs', 'hidden-sm', 'hidden-lg', 'hidden-md', 'active', 'btn-'];

I have a function that gets all css classes in the DOM. But i want to check if this class should be added to a new array or not. So i can use indexOf for this:

return filterClasses.indexOf('col-sm-12');

This returns a true, so this class should be ignored.

But now i have a class that is btn-primary. As you see in my array i have the btn- added in it. I want to exclude all classes that contains the word btn- . How can i achieve this?

Current function:

function setupShouldAddClass( cssClass, filterClasses )
{
    // If the cssClass exists in the filterClasses then false
    if ( filterClasses.indexOf(cssClass) > 0 )
    {
        return true;
    }

    filterClasses.forEach(function ( item )
    {
        if ( stringContains(item, cssClass) )
        {
            return true;
        }
    });

    return false;
}

function stringContains( needle, haystack )
{
    return (haystack.indexOf(needle) !== -1);
}

You need to use Array#some and check against each value and return true if found.

function setupShouldAddClass(cssClass, filterClasses) {
    return filterClasses.indexOf(cssClass) !== -1 || filterClasses.some(function (item) {
        return stringContains(item, cssClass);
    });
}

Maybe you can solve your issue using regular expressions instead of using imperative code:

 var classBlackListRegExp = /(col-sm-12|hidden-xs|hidden-sm|hidden-lg|hidden-md|active|^btn-.+)/i; var result = classBlackListRegExp.test("btn-whatever"); console.log(result); 

Check the ^btn-.+ part. This matches anything starting with "btn-" .

I believe that your scenario is the ideal use case of regular expressions!

OP concerns if class black list is very large

OP said:

what im wondering is, that if i add more then 100 classes, how does this handle the line breaks?

You can join the whole array of black-listed strings and create a RegExp object with it as follows:

 // I use a templated string and String.prototype.join // to create a regular expression from a given array: var classBlackListRegExp = new RegExp(`(${[ 'col-sm-12', 'hidden-xs', 'hidden-sm', 'hidden-lg', 'hidden-md', 'active', '^btn-.+' ].join("|")})`, "i"); var result = classBlackListRegExp.test("btn-whatever"); console.log(result); 

I would loop over them like this.

function setupShouldAddClass( cssClass, filterClasses )
{
    // If the cssClass exists in the filterClasses then false
    var ret = true;
    filterClasses.forEach(function(el) {
      if (cssClass.indexOf(el) >= 0) {
        ret = false;
      }
    });

    return ret;
}

How about bringing the cssClass to what you needed to be compared to:

var transformedToMyNeedsCSS = "btn-primary".replace(/^(btn[-])(?:.*)/,"$1");
 // --> Output "bnt-"

And then you compare as you are doing it now:

if ( filterClasses.indexOf(transformedToMyNeedsCSS) > 0 )
    {
        return true;
    }

There's a whole host going wrong here. Let's deal with it step by step:

First

if ( filterClasses.indexOf(cssClass) > 0 )

That is incorrect because indexOf returns -1 if the search term is not found. It returns 0 if it is the first item in the array. So you want >= 0 .

Second, the forEach loop:

filterClasses.forEach(function ( item )
{
    if ( stringContains(item, cssClass) )
    {
        return true;
    }
});

This achieves nothing. As in, genuinely nothing. Because you are inside a new function (the callback to forEach ) return only returns from the inner function. And the return value is then discarded. What this code actually does is loop all the way through the array and do nothing. What you actually want is a clever function called Array.prototype.some . This loops through the array and tests each element. If you return true on any of the elements, some returns true . Otherwise it returns false .

So your code could look like this:

return filterClasses.some(function(element) {
    return stringContains(item, cssClass);
}

Now we want to ignore all classes where they begin with btn- . I presume this means that you want to return false if the class begins with btn- .

if (cssClass.indexOf('btn-') === 0) {
    return false;
}

So your function now looks like:

function setupShouldAddClass( cssClass, filterClasses )
{
    if (cssClass.indexOf('btn-') === 0) {
        return false;
    }

    // If the cssClass exists in the filterClasses then false
    if ( filterClasses.indexOf(cssClass) >= 0 )
    {
        return true;
    }

    return filterClasses.some(function(element) {
        return stringContains(item, cssClass);
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM