73

Is there a way in JavaScript to get Boolean value for a match of the string against the array of regular expressions?

The example would be (where the 'if' statement is representing what I'm trying to achieve):

var thisExpressions = [ '/something/', '/something_else/', '/and_something_else/'];
var thisString = 'else';

if (matchInArray(thisString, thisExpressions)) {

} 
X X
  • 81
  • 7
user398341
  • 6,339
  • 17
  • 57
  • 75

10 Answers10

135

Using a more functional approach, you can implement the match with a one-liner using an array function:

ECMAScript 6:

const regexList = [/apple/, /pear/];
const text = "banana pear";
const isMatch = regexList.some(rx => rx.test(text));

ECMAScript 5:

var regexList = [/apple/, /pear/];
var text = "banana pear";
var isMatch = regexList.some(function(rx) { return rx.test(text); });
andersh
  • 8,105
  • 6
  • 39
  • 30
22

http://jsfiddle.net/9nyhh/1/

var thisExpressions = [/something/, /something_else/, /and_something_else/];
var thisExpressions2 = [/else/, /something_else/, /and_something_else/];
var thisString = 'else';

function matchInArray(string, expressions) {

    var len = expressions.length,
        i = 0;

    for (; i < len; i++) {
        if (string.match(expressions[i])) {
            return true;
        }
    }

    return false;

};

setTimeout(function() {
    console.log(matchInArray(thisString, thisExpressions));
    console.log(matchInArray(thisString, thisExpressions2));
}, 200)​
GillesC
  • 10,647
  • 3
  • 40
  • 55
  • 2
    Why not strip the res variable out entirely, return true in your if statement and return false at the end. Then it will quit on finding the first match. – Arth Apr 14 '12 at 10:07
  • Also i'd use expressions[i].test(string) rather than string.match() – Arth Apr 14 '12 at 10:08
  • 2
    Although this code may answer the question, providing additional context regarding _why_ and/or _how_ it answers the question would significantly improve its long-term value. Please [edit] your answer to add some explanation. – Toby Speight May 06 '16 at 11:49
  • What about let's say I wanted the index of the value that was matched? – Si8 Oct 23 '18 at 17:50
6

You could use .test() which returns a boolean value when is find what your looking for in another string:

var thisExpressions = [ '/something/', '/something_else/', '/and_something_else/'];
var thisString = new RegExp('\\b' + 'else' + '\\b', 'i');
var FoundIt = thisString.test(thisExpressions);  
if (FoundIt) { /* DO STUFF */ }
Thierry Blais
  • 2,848
  • 22
  • 41
  • 1
    RegExp.prototype.test() cannot be used with an Array. It takes a string. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test – gdibble Oct 14 '15 at 16:57
  • 1
    @gdibble it will work, because `test` it calls `toString` on the supplied argument, which, for array, will `join()`. Probably not advisable though! – WickyNilliams Oct 23 '15 at 10:42
  • Example: `/monkey/.test({ toString : () => "monkey" }) // true` – WickyNilliams Oct 23 '15 at 10:42
  • @Likwid_T - what does '\\b' mean ? I know that 'i' means case insensitive, but I could not find online what \\b means. Also, why do you have it twice? – GK79 Nov 15 '15 at 15:17
  • @WickyNilliams fair enough my friend ;) – gdibble Nov 18 '15 at 01:15
  • 1
    @GK79 a `\b` is a word-boundary - such that you could match `/\broller\b/` in just the word 'roller' but it would not match 'rollercoaster', however if you took off the trailing `\b` then it would match the first part of 'rollercoaster' – gdibble Nov 18 '15 at 01:17
2

Consider breaking this problem up into two pieces:

  1. filter out the items that match the given regular expression
  2. determine if that filtered list has 0 matches in it
const sampleStringData = ["frog", "pig", "tiger"];

const matches = sampleStringData.filter((animal) => /any.regex.here/.test(animal));

if (matches.length === 0) {
  console.log("No matches");
}
user1429980
  • 6,872
  • 2
  • 43
  • 53
1

look this way...

function matchInArray(stringSearch, arrayExpressions){
    var position = String(arrayExpressions).search(stringSearch);
    var result = (position > -1) ? true : false
    return result;
}
  • 1
    Although this code may answer the question, providing additional context regarding _why_ and/or _how_ it answers the question would significantly improve its long-term value. Please [edit] your answer to add some explanation. – Toby Speight May 06 '16 at 11:49
1

You can join all regular expressions into single one. This way the string is scanned only once. Even with a sligthly more complex regular expression.

var thisExpressions = [ /something/, /something_else/, /and_something_else/];
var thisString = 'else';


function matchInArray(str, expr) {
    var fullExpr = new RegExp(expr
        .map(x=>x.source) // Just if you need to provide RegExp instances instead of strings or ...
        // .map(x=>x.substring(1, x.length -2)  // ...if you need to provide strings enclosed by "/" like in original question.
        .join("|")
    )
    return str.match(fullExpr);

};


if (matchInArray(thisString, thisExpressions)) {
    console.log ("Match!!");
} 

In fact, even with this approach, if you need check the same expression set against multiple strings, this is a few suboptimal because you are building (and compiling) the same regular expression each time the function is called.

Better approach would be to use a function builder like this:

var thisExpressions = [ /something/, /something_else/, /and_something_else/];
var thisString = 'else';

function matchInArray_builder(expr) {
    var fullExpr = new RegExp(expr
        .map(x=>x.source) // Just if you need to provide RegExp instances instead of strings or ...
        // .map(x=>x.substring(1, x.length -2)  // ...if you need to provide strings enclosed by "/" like in original question.
        .join("|")
    )   

    return function (str) {
        return str.match(fullExpr);

    };
};  

var matchInArray = matchInArray_builder(thisExpressions);

if (matchInArray(thisString)) {
    console.log ("Match!!");
} 
bitifet
  • 3,514
  • 15
  • 37
  • What about let's say I wanted the index of the value that was matched? – Si8 Oct 23 '18 at 17:50
  • 1
    `matchInArray(thisString, thisExpressions).index` – bitifet Oct 23 '18 at 18:47
  • Would it be going after the `var matchInArray = matchInArray_builder(thisExpressions);`? like this: `var matchInArray = matchInArray_builder(thisExpressions); var index = matchInArray(thisString, thisExpressions).index`? – Si8 Oct 23 '18 at 19:02
  • No. I put an extra parameter by mistake. `matchInArray()` function returns the outcome of `String.match()`. Hence, in fact the "if" condition isn't a boolean value but a complete structure (which evaluates to true) reporting the matched substring and its position… – bitifet Oct 23 '18 at 19:16
  • ahhhhh... i misread your return statement within the function :) – Si8 Oct 23 '18 at 19:22
  • But it is essential. The function would return undefined (falsy) unconditionally otherwise ;-) – bitifet Oct 23 '18 at 19:26
1

Andersh's solution will not work if you have global flags.
A true return will toggle on and off on future identical tests.

regexArray.some( rx => rx.test( "a" ))    // true
regexArray.some( rx => rx.test( "a" ))    // false
regexArray.some( rx => rx.test( "a" ))    // true

(read why here)

This works and is also a one-liner:

const isMatch = regexList.map( rx => rx.source).includes( string )

.source returns the text string of the RegExp pattern.
.map returns an array of these strings.
.includes returns if the string is in the array
(if you need the index, use .indexOf)

Alternatively:

function isInsideArray( string, regexArray ){
  return regexArray.map( regex => regex.source).includes( string )
}

function isInsideArray_Andersh( string, regexArray ){
  return regexArray.some( rx => rx.test( string )) 
}

    
const list_rx = [ /apple/g, /pear/g, /banana/g ],
      string  = "pear"

console.log( isInsideArray( string, list_rx ))
console.log( 'Andersh:', isInsideArray_Andersh( string, list_rx ))
console.log( 'Andersh (same test):', isInsideArray_Andersh( string, list_rx ))
Andrei Cleland
  • 378
  • 3
  • 10
0
let expressions = [ '/something/', '/something_else/', '/and_something_else/'];

let str = 'else';

here will be the check for following expressions:

if( expressions.find(expression => expression.includes(str) ) ) {

}

using Array .find() method to traverse array and .include to check substring

Mubeen Khan
  • 997
  • 1
  • 10
  • 11
0

If you would like to use String.match(), in case your array contains both match strings and regular expressions, you can do

let str = "The quick brown fox";
let matches = ["fox", "The.*fox", /the.*fox/i];
let strInMatches = matches.some(match => str.match(match));
console.log(strInMatches);
aljgom
  • 7,879
  • 3
  • 33
  • 28
-2

So we make a function that takes in a literal string, and the array we want to look through. it returns a new array with the matches found. We create a new regexp object inside this function and then execute a String.search on each element element in the array. If found, it pushes the string into a new array and returns.

// literal_string: a regex search, like /thisword/ig
// target_arr: the array you want to search /thisword/ig for.

function arr_grep(literal_string, target_arr) {
  var match_bin = [];
  // o_regex: a new regex object.
  var o_regex = new RegExp(literal_string);
  for (var i = 0; i < target_arr.length; i++) {
    //loop through array. regex search each element.
    var test = String(target_arr[i]).search(o_regex);
    if (test > -1) {
    // if found push the element@index into our matchbin.
    match_bin.push(target_arr[i]);
    }
  }
  return match_bin;
}

// arr_grep(/.*this_word.*/ig, someArray)
Mod
  • 1
  • 1