动态创建正则表达式组以匹配低于或高于所需值的模式

Dynamically create RegExps groups to match patterns lower than or greater than a desired value

我创建了两个 JavaScript 函数来动态创建 RegExps 匹配小于或大于参数中发送的数字的组。这些函数的目的是做一些类似 this or this 的事情,但是动态地,我需要它来构建一个应用程序 RegExps,这段代码创建了一个匹配特定数字组的组,稍后你可以使用返回小组完成你的最后 RegExp.

这是创建 RegExp 以查找大于所需值的形态的函数:

//Find greater than numbers
function getGreaterUintRegEx(n) {
  var s = String(n);
  var t = s.length,
    a = [];
  for (var i = 1; i < t + 1; i++) {
    switch (s.charAt(t - i)) {
      case "9":
        a.push((Number(s.slice(0, t - i)) + 1) + "0" + (new Array(i)).join("\d"));
        break;
      case "8":
        a.push(s.slice(0, t - i) + "9" + (new Array(i)).join("\d"));
        break;
      default:
        a.push(s.slice(0, t - i) + "[" + (Number(s.charAt(t - i)) + 1) + "-9]" + (new Array(i)).join("\d"));
    }
  }
  a.push("\d{" + (t + 1) + ",}");
  a = a.filter(function(s, i) {
    return a.indexOf(s) == i;
  });
  return "(" + a.join("|") + ")";
}

使用示例:

var regstr = getGreaterUintRegEx(124);
// (12[5-9]|1[3-9]\d|[2-9]\d\d|\d{4,})

var regstr = getGreaterUintRegEx(500);
// (50[1-9]|5[1-9]\d|[6-9]\d\d|\d{4,})

这里是创建 RegExp 以查找低于所需值的形态的函数:

//Find lower than numbers
function getLowerUintRegEx(n) {
  if (n == 0) return false;
  if (n == 1) return "(0)";
  if (n > 0 && n < 10) return "[0-" + (n - 1) + "]";
  var s = String(n);
  var t = s.length,
    a = [];
  for (var i = 1; i < t + 1; i++) {
    switch (s.charAt(t - i)) {
      case "0":
        a.push(((s.slice(0, t - i) == "1") ? "" : (Number(s.slice(0, t - i)) - 1)) + "9" + (new Array(i)).join("\d"));
        break;
      case "1":
        a.push("[1-9]" + (new Array(i - 1)).join("\d"));
        break;
      default:
        a.push(s.slice(0, t - i) + "[0-" + (Number(s.charAt(t - i)) - 1) + "]" + (new Array(i)).join("\d"));
    }
  }
  if (t - 1 > 1) a.push("\d{1," + (t - 1) + "}");
  a.push("0");
  a = a.filter(function(s, i) {
    return a.indexOf(s) == i;
  });
  return "(" + a.join("|") + ")";
}

使用示例:

var regstr = getLowerUintRegEx(498);
// (49[0-7]|4[0-8]\d|[0-3]\d\d|\d{1,2}|0)

var regstr = getLowerUintRegEx(125);
// (12[0-4]|1[0-1]\d|[1-9]\d|\d{1,2}|0)

我想让这些功能更简单、更慢。大数字需要一秒钟以上。还有其他更简单的方法吗?有人知道步骤更少的稳健算法吗?

方法复杂,你的方法。以及限制方式。

function getInts(str){
    return String(str).match(/[+-]?\d+/g).map(Number);
}
function greaterThan(w){
    return function(v){ return v > w } 
}
function lowerThan(w){ //
    return function(v){ return v < w } 
}

getInts(someString).filter( greaterThan(473) )

或更通用的方法:

var is = (function(is){
    for(var key in is) is[key] = Function("w", "return function(v){return v " + is[key] + " w}");
    return is;
})({
    eq: "===",
    neq: "!==",
    gt: ">",
    lt: "<",
    gteq: ">=",
    lteq: "<="
});
is.typeof = function(w){ return function(v){ return typeof v === w }};

getInts(someString).filter( is.lt(92) );

这不是我解决问题的方法,但您不是在寻找更好的解决方案,而是实际上想要审查您的代码、建议和优化,以提供与原始功能相同的功能(有效代码)。

无论如何,下面是一个建议。代码可读性更强,我无意测试其性能。

var reduceRight = Function.prototype.call.bind(Array.prototype.reduceRight);

//Find greater than numbers
function getGreaterUintRegEx(n) {
  var s = String(n);
  var t = s.length - 1;
  var a = reduceRight(s, function(acc, v, i) {
    var x = s.slice(0, i);
    if (v === '9') {
      x = Number(x) + 1 + '0';
    } else if (v === '8') {
      x += '9';
    } else {
      x += '[' + (Number(v) + 1) + '-9]';
    }
    acc.push(x + '\d'.repeat(t - i));
    return acc;
  }, []);
  a.push('\d{' + (t + 2) + ',}');
  return '(' + a.join('|') + ')';
}

//Find greater than numbers: original
function getGreaterUintRegEx1(n) {
  var s = String(n);
  var t = s.length,
    a = [];
  for (var i = 1; i < t + 1; i++) {
    switch (s.charAt(t - i)) {
      case "9":
        a.push((Number(s.slice(0, t - i)) + 1) + "0" + (new Array(i)).join("\d"));
        break;
      case "8":
        a.push(s.slice(0, t - i) + "9" + (new Array(i)).join("\d"));
        break;
      default:
        a.push(s.slice(0, t - i) + "[" + (Number(s.charAt(t - i)) + 1) + "-9]" + (new Array(i)).join("\d"));
    }
  }
  a.push("\d{" + (t + 1) + ",}");
  a = a.filter(function(s, i) {
    return a.indexOf(s) == i;
  });
  return "(" + a.join("|") + ")";
}

var out = document.getElementById('out');
for (var i = 0; i < 100000; i += 1) {
  var suggested = getGreaterUintRegEx(i);
  var original = getGreaterUintRegEx1(i);
  if (suggested !== original) {
    var txt = suggested + '!==' + original;
    out.textContent = txt;
    throw new Error(txt);
  }
}
out.textContent = suggested + '\n' + original + '\nSame results';
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.4.1/es5-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.1/es6-shim.js"></script>
<pre id="out"></pre>

只需删除不必要的数据结构(每次调用都会创建几个 Array 并且需要一个 Function、none),您将获得很大的加速。

这里重写了 getGreaterUintRegEx:

function getGreaterUintRegEx(n) {
  var nStr = String(n);
  var len = nStr.length;
  var result = '(';
  var ds = '';
  var i;

  for (i = len - 1; i >= 0; i--) {
    switch (nStr.charAt(i)) {
      case '9': result += `${+nStr.slice(0, i) + 1}0${ds}|`; break;
      case '8': result += `${nStr.slice(0, i)}9${ds}|`; break;
      default:  result += `${nStr.slice(0, i)}[${+nStr.charAt(i) + 1}-9]${ds}|`;
    }
    ds += '\d';
  }
  return `${result}\d{${len + 1},})`;
}

我使用 ES6 模板字符串只是为了提高可读性。它们目前在常绿浏览器中受支持,但如果您想支持 IE11,则需要将它们换成旧的 '' + ''