5

I want to combine two regexes in one, but I don't know how to do it in my case. So, I want to do next thing: function that format number to US-format, simply adding commas for 1000, like 1,000 and so on. (I know about toLocaleString('en-US') and Intl.NumberFormat.prototype.format but these are unsuitable for my case). For do it using regex I tried this expression: /\d(?=(\d{3})+\.)/g and it works well, but only if our number contains dot (e.g. 1000.23), but if there is no dot, the current regex won't work. (Proof: https://regex101.com/r/93O0gJ/1)

There is another regex that I have to make my function work properly: /\d(?=(\d{3})+$)/g but it works properly only when we have no dot's at all. If we have dots, it will replace the float or fractional part with commas, and it is not a correct behaviour for my requirements. (My number would be like "1000.12,345,678" for number 1000.12345678). But without dots in number everything works well. (Proof: https://regex101.com/r/BHikK7/1)

So, for my case I create function that checks: if number has dots, I use the 1st regex, if doesn't, I use 2nd:

const formatNumberToUSFormat = (numberToFormat: number):string => {
  const stringNumber = numberToFormat.toString()

  return stringNumber.match(/\./g) ?
    stringNumber.replace(/\d(?=(\d{3})+\.)/g, '$&,') : 
    stringNumber.replace(/\d(?=(\d{3})+$)/g, '$&,')
}

My main question — how to combine two regex in one in my case and by that avoid unnecessary checks for dots and so on. Thanks in advance.

Avernikoz
  • 463
  • 2
  • 5
  • 15

3 Answers3

3

Since there is only (?=...) 'followed by' expression and no 'preceded by' - you can reverse the string in order to properly use 'followed by' like this:

const num = '1234567890.12345';
const result = [...[...num] // destructing the string
  .reverse().join('') // reversing the original string
  .replace(/(?:\d+\.)?(\d{3}(?=\d))/g,'$&,')]
  .reverse().join(''); // reversing the result back to normal
console.log(result);

But this approach is faaar from optimal!
Do not use it if you have a lot of data to process!

Pavel Agarkov
  • 3,633
  • 22
  • 18
1

Regexp from hell, but it works )))

const num = '1234567890.123456';
const result  = num.replace(new RegExp('\\B(?=(\\d{3})+'+(~num.indexOf('.')?'\\.':'$')+')','g'),',');

console.log(result);

Original answer: https://stackoverflow.com/a/46371080/6776408

SIARHEI PAKHUTA
  • 175
  • 2
  • 12
0

Check on the next regex (?:(?<=^|[^\d.])(\d{1,3})(?=(?:\d{3})+(?:\D|$))|\G)(\d{3}).

To try the regex online and get an explanation, please click here.

Andrei Odegov
  • 2,925
  • 2
  • 15
  • 21