4

Is it possible to have a dynamically generated string

var string= "a,b,c";

and make a regex out of that that accepts any of the strings words as accepted matches?

regExApproved = new RegExp(string, 'ig');

So that we can search a data-attribute of an element and show it if it has any of the accepted matches in the attribute

$(this).attr("data-payment").match(regExApproved)

The problem im facing is the regex takes the whole string and makes that the only match case.
I need the regex to break the string down and accept ANY word in it as a match

Is this possible? I do not want to use a forloop and make LOTS of different regex Matches for each word in the string but maybe I have to?

Tommy
  • 2,355
  • 1
  • 19
  • 48
Chris Cullen
  • 110
  • 9

2 Answers2

1

I suggest using

var regExApproved = new RegExp(string.split(",").map(x => x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'), 'i');

Then, to check if a regex matches a string, it makes more sense to use RegExp#test method:

regExApproved.test($(this).attr("data-payment"))

Notes:

  • .split(",") - splits into comma-separated chunks
  • .map(x => x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')) (or .map(function(x) return x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); })) - escapes the alternatives
  • .join('|') creates the final alternation pattern.

Edit

It seems that your string is an array of values. In that case, use

var string= ['visa','mastercard'];
var regExApproved = new RegExp(string.join('|'), 'i');
// If the items must be matched as whole words:
// var regExApproved = new RegExp('\\b(?:' + string.join('|') + ')\\b', 'i');
// If the array items contain special chars:
// var regExApproved = new RegExp(string.map(x => x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'), 'i');
console.log(regExApproved.test("There is MasterCard here"));
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks but it this Regex which is what is produced : /\b(["visa"|"mastercard"])\b/gi Doesnt Match my data-value: "all, visa, mastercard, ideal, entropay" – Chris Cullen Nov 02 '18 at 17:25
  • 1
    @ChrisCullen What is your real input string? I doubt it is a string, it looks as if your `string` is in fact an *array*. Just do not use `.split(",")` then, omit this command. Try `new RegExp(string.map(x => x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'), 'i')`. There may be other adjustments to code required depending on what you are doing with the regex (replace or match). – Wiktor Stribiżew Nov 02 '18 at 18:24
  • @ChrisCullen I added several solutions. All are based on a single regex that is created once dynamically and only 1 regex test operation is required to check if any is present in the string. – Wiktor Stribiżew Nov 02 '18 at 18:37
  • Thankyou wiktor. Here is the string: Object.values = function(object) { var values = []; for(var property in object) { values.push(object[property]); } return values; } var val = Object.values(checkboxes); var string = JSON.stringify(val); AS you can see string is a stringifed object. When I tried to use your new regEx it said string.map is not a function – Chris Cullen Nov 03 '18 at 21:12
  • 1
    @ChrisCullen Why stringify it then? If it is an array, why not pass the `val` with the array of strings to the RegExp constructor? – Wiktor Stribiżew Nov 03 '18 at 21:18
  • 1
    Stribizew I simply used val instead of the stringified string and I think it may actually work! – Chris Cullen Nov 03 '18 at 21:22
1

If your string is a list of comma-separated words, you can split it by comma then use a combination of Array methods to check if any word is matched inside the test string.

This is how should be your code:

string.split(",").map(s => new RegExp('\\b' + s + '\\b')).some(r => $(this).attr("data-payment").match(r))

Where we have:

  • string.split(",") to split the string by comma.
  • .map(s => new RegExp('\\b' + s + '\\b')) to return a relevant regex for each word in the string using word-boundary.
  • .some(r => $(this).attr("data-payment").match(r)) to check if our string matches any one of the created regexes.

Demo:

var string = "is,dog,car";

let str = "this is just a test";

if (string.split(",").map(s => new RegExp('\\b' + s + '\\b')).some(r => str.match(r))) {
  console.log("Matched");
}
cнŝdk
  • 31,391
  • 7
  • 56
  • 78