Ad

Dynamically Create RegExps Groups To Match Patterns Lower Than Or Greater Than A Desired Value

- 1 answer

I've made two JavaScript functions to dynamically create RegExps groups that match numbers lower than or greater than the number that is sent in the parameter. The purpose of these functions is to do something like this or this but dynamically, I need it for an App for building RegExps, this code made a group that match a particular group of numbers, later you could use the returned group to complete your final RegExp.

Here is the function to create a RegExp to find patterns greater than a desired value:

//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("|") + ")";
}

Example of use:

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,})

And here is the function to create a RegExp to find patterns lower than a desired value:

//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("|") + ")";
}

Example of use:

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)

I want to make these functions more simply and less slow. It takes more than a second with big numbers. Is there any other easier method? Somebody knows a robust algorithm with less steps?

Ad

Answer

You'll get a big speedup just by removing unnecessary data structures (each call creates several Arrays and a Function, none are needed).

Here's a rewrite of just 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},})`;
}

I've used ES6 template strings just for readability. They're currently supported across evergreen browsers, but you'll want to swap them for the old '' + '' if you want to support IE11.

Ad
source: stackoverflow.com
Ad