如何在Javascript中编写一种有效的方式来处理匹配模式?

时间:2019-05-09 00:13:32

标签: javascript

我想生成与特定模式匹配的字符串。例如,该函数将带有两个参数:

function parsePattern(pattern, string) {}

可以接受的模式可以是“(你好|嗨),%i,(你好吗?很高兴见到你)”,以及第二个参数是否以此方式设置为“约翰”

parsePattern('(hello|hi), %i, (how are you|nice to see you)', 'John')

我希望输出具有所有可能的组合:

 'hello, John, how are you'
 'hello, John, nice to see you'
 'hi, John, how are you'
 'hi, John, nice to see you'

实现此目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

您正在寻找与正则表达式通常相反的功能,因此对于像\w+这样的更通用的正则表达式模式来说是不可能的。但是,如果您只是想像示例中那样为A|B类型的模式生成结果,下面的一些代码将完成此操作。这利用StackOverflow's own formatUnicorn function以及给定here的笛卡尔积函数。您当然可以用自己的替换它们。

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;
}