Charles Clayton
Charles Clayton

Reputation: 17946

How to efficiently check if any substring in an array is contained in another string

I want to have something that checks if any substring in a list of strings is included in string. I have something that works, but I'm hoping there is something cleaner and more efficient, preferably just in one line I can call like if(string.contains(list.any)) or something.

var list = ['aa','bb','cc','dd'];
var string = "nygaard"; // true because "aa" is in "nygaard".

for (var i = 0; i < list.length; i++) {
    if( string.indexOf( list[i] ) > -1 ) {
        alert("True");
        break;
    }
}

Upvotes: 2

Views: 342

Answers (3)

Harpreet Singh
Harpreet Singh

Reputation: 2671

var list = ['aa','bb','cc','dd'];
var string = "nygaard"; 
var patt = new RegExp(list.join('|'))
// regEx -  /aa|bb|cc|dd/
patt.test(string)
//output true

Demo

Explanation

  • Dynamically create a regEx using new RegExp
  • for checking existance of multiple SubString we have | operator in RegEx
  • Use Array.join('|') to dynamically make a regExp like this aa|bb|cc
  • use test func to validate String

Edit - For Complex Cases - Problem is strings in list may have to be escaped for RegEx to work, Pointed By - @GabrielRatener

Compairing to my solu, @GabrielRatener's solution is better

var list = ['aa','bb','cc','dd', 'ab?', '(aa)'];
list = list.sort(function(a, b) {
    if (a>b) return -1;
    else if (a<b) return 1;
    else return 0;
});
list = list.join(" ").replace(/[^\w\s]/g, function($1) {
return '\\' + $1
}).split(/\s/);
//["dd", "cc", "bb", "ab\?", "aa", "\(aa\)"]
//sorting needed to match "ab?" before single "a" as "b" will become optional
//due to "?"

//after processing
var string = "nygaard"; 
var patt = new RegExp(list.join('|')) // RegExp ->  /dd|cc|bb|ab\?|aa|\(aa\)/
patt.test(string)
//true

Upvotes: 3

Gabriel Ratener
Gabriel Ratener

Reputation: 605

EcmaScript 6 is proposing a contains method for strings such that you could do this:

function stringContainsArray(str, array){
    for (var i = 0; i < array.length; i++){
        if (str.contains(array[i])){
            return true;
        }
    }
    return false;
}

var list = ['aa','bb','cc','dd'];
var string = "nygaard"; // true because "aa" is in "nygaard".

console.log(stringContainsArray(list));
//  => true

Since implementation will likely remain spotty in the major browsers and other runtimes for the near future, you should add the following code for compatibility before the stringContainsArray function:

// String.prototype.contains will be implemented in
// the major browsers in the not too distant future
// this will add the same functionality to browsers
// or other runtimes that do not currently support it
if ( !String.prototype.contains ) {
    String.prototype.contains = function() {
        return String.prototype.indexOf.apply( this, arguments ) !== -1;
    };
}

this may help: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/contains

You can also extend the string prototype to have a simple method:

String.prototype.containsArray = function(array){
    return stringContainsArray(this, array);
}

Then you can simpy do:

"nygaard".containsArray(list);
//  => true

Upvotes: 2

Shmoopy
Shmoopy

Reputation: 649

Why not just put your loop in its own function you can call?

function stringContains(string, list) {
    for (var i = 0; i < list.length; i++) {
        if( string.indexOf( list[i] ) > -1 )
            return true;
    }
    return false;
}

and then call it like this:

var list = ['aa','bb','cc','dd'];
var string = "nygaard";

if(stringContains(string, list))
   alert("True");

If you're looking for a javascript library function, I don't believe there is one.

Upvotes: 2

Related Questions