Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine two regex in one when we format number to US format

Tags:

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.

like image 806
Avernikoz Avatar asked Aug 15 '18 18:08

Avernikoz


2 Answers

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!

like image 178
Pavel Agarkov Avatar answered Oct 11 '22 14:10

Pavel Agarkov


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

like image 35
SIARHEI PAKHUTA Avatar answered Oct 11 '22 13:10

SIARHEI PAKHUTA