Reputation: 2555
I would like to generate strings that match a certain pattern. For example, the function would take two parameters:
function parsePattern(pattern, string) {}
And the accepted pattern could be '(hello|hi), %i, (how are you|nice to see you)' and if the 2nd param is set as 'John' in this way
parsePattern('(hello|hi), %i, (how are you|nice to see you)', 'John')
I would like the output to have all the possible combinations:
'hello, John, how are you'
'hello, John, nice to see you'
'hi, John, how are you'
'hi, John, nice to see you'
What's the best way to achieve this?
Upvotes: 0
Views: 155
Reputation: 196
You're looking to do the reverse of what regex is normally used for, so it wouldn't be possible for more generalized regex patterns like \w+
. But if you're just looking to generate results for the A|B
type of patterns like in your example, here's some code that will accomplish this. This makes use of StackOverflow's own formatUnicorn function as well as a Cartesian product function as given here. You can replace these with your own, of course.
JSFiddle: https://jsfiddle.net/aro108zc/
String.prototype.formatUnicorn = String.prototype.formatUnicorn ||
function () {
"use strict";
var str = this.toString();
if (arguments.length) {
var t = typeof arguments[0];
var key;
var args = ("string" === t || "number" === t) ?
Array.prototype.slice.call(arguments)
: arguments[0];
for (key in args) {
str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);
}
}
return str;
};
function cartesianProduct(arr) {
return arr.reduce(function (a, b) {
return a.map(function (x) {
return b.map(function (y) {
return x.concat([y]);
})
}).reduce(function (a, b) { return a.concat(b) }, [])
}, [[]])
}
function parsePattern(pattern, str) {
var regex = /\(([^|()]+\|)*[^|()]+\)/g;
var results = [];
var matches = pattern.match(regex);
// replace input string match groups with format strings
matches.forEach(function (el, idx) {
pattern = pattern.replace(el, '{' + (idx + 1) + '}');
});
// split matches into parts
var matchesSplit = [];
matches.forEach(function (el, idx) {
matchesSplit[idx] = el.replace(/[()]/g, '').split('|');
});
// generate result strings
matchesSplit.splice(0, 0, [str]);
cartesianProduct(matchesSplit).forEach(function (el) {
results.push(pattern.formatUnicorn(el));
});
return results;
}
Upvotes: 1