1

How might I efficiently use regex to match input that could be a positive or negative dollar amount or percentage.

  • Input could start with optional + or -
  • Followed by optional $
  • Then digits with optional comma as a digit group separator following a digit in the thousands/hundred thousands/millions...
  • Followed by an optional decimal point and one or two digits
  • And finally a possible %, but only if the input doesn't contain a $, and the number is from -100.00 to +100.00

So it would match input like: 12, -60, $25.50, -$1.5, +$25,000, 5.5%, -100%, +100%, 0.01%

And return false with input like: Text, +$10%, -5.001

I've been evaluating them separately with:

function percentValue(input) {
    regex = /^[+-]?\$?(?=.)(\d*|\d{1,3}(,\d{3})*)?(\.\d{1,2})?$/;
    return regex.test(input);
}

function dollarValue(input) {
    regex = /^[+-]? *100(\.0{0,2})? *%?$|^[+-]? *\d{1,2}(\.\d{1,2})? *%?$/;
    return regex.test(input);
}

Results

percentValue('5.5%');  // True
percentValue('-100%'); // True
percentValue('+.01%'); // True
percentValue('0.001'); // False
percentValue('101%');  // False
percentValue('$100%'); // False

dollarValue('+$12');    // True
dollarValue('-$60.5');  // True
dollarValue('$25,000'); // True
dollarValue('-$5.001'); // False
dollarValue('1,00.25'); // False
dollarValue('$text');   // False

I've been unsuccessful trying to combine them into one. Should I be using another lookahead for the percentage?

jds580s
  • 59
  • 1
  • 8
  • 2
    Use two regular expressions, one for dollar amount, another for percentage. You can then combine them with `|` to match either type. – Barmar Jul 13 '20 at 22:48
  • 2
    StackOverflow is not a free coding service. You're expected to [try to solve the problem first](https://meta.stackoverflow.com/questions/261592/how-much-research-effort-is-expected-of-stack-overflow-users). Please update your question to show what you have already tried in a [mcve]. For further information, please see [ask], and take the [tour] :) – Barmar Jul 13 '20 at 22:49
  • I would advise using two separate regular expressions as Barmar stated above. You can do one if statement that checks for the dollar sign regex followed by one if statement that checks for the percentage regex. It doesn't have to be all done in one regex. I would advise using regexstorm.net/reference to see examples and then use regexstorm.net/tester to test. You just play around with the regex until it's matching what you want. – Mark S Jul 13 '20 at 23:02
  • @Barmar, Thanks, edited to add code, appreciate the kindness. – jds580s Jul 14 '20 at 18:05
  • @MarkS @Barmar Thanks for the pointer. I was thinking of a more complicated solution. Used `let regex = /^[+-]?\$?(?=.)(\d*|\d{1,3}(,\d{3})*)?(\.\d{1,2})?$|^[+-]? *100(\.0{0,2})? *%?$|^[+-]? *\d{1,2}(\.\d{1,2})? *%?$/;` with a simple OR and it works great. – jds580s Jul 14 '20 at 18:08
  • Just combine them with `|`: `/^[+-]?\$?(?=.)(\d*|\d{1,3}(,\d{3})*)?(\.\d{1,2})?$|^[+-]? *100(\.0{0,2})? *%?$|^[+-]? *\d{1,2}(\.\d{1,2})? *%?$/` – Barmar Jul 14 '20 at 18:08

1 Answers1

0

var test = [
    '12',
    '-60',
    '$25.50',
    '-$1.5',
    '+$25,000',
    '5.5%',
    '-100%',
    '+100%',
    '0.01%',
    'Text',
    '+$10%',
    '-5.001',
];
console.log(test.map(function (a) {
  return a+' :'+/^[+-]?(?:\$?\d{1,3}(?:,\d{3})*(?:\.\d\d?)?|(?:100|\d\d?)(?:\.\d\d?)?%)$/.test(a);
}));

Demo & explanation

Toto
  • 83,193
  • 59
  • 77
  • 109