I need to display a formatted number on a web page using JavaScript. I want to format it so that there are commas in the right places. How would I do this with a regular exp
Brandon,
I didn't see too many answers working the regex from the decimal point back, so I thought I might chime in.
I wondered if there is any elegant benefit to re-writing the regexp to scan from the back forward...
function addCommas(inputText) {
// pattern works from right to left
var commaPattern = /(\d+)(\d{3})(\.\d*)*$/;
var callback = function (match, p1, p2, p3) {
return p1.replace(commaPattern, callback) + ',' + p2 + (p3 || '');
};
return inputText.replace(commaPattern, callback);
}
>> Fiddle Demo <<
This accounts for any decimal place.
If you really want a regex, you can use two in a while loop:
while(num.match(/\d{4}/)) {
num = num.replace(/(\d{3})(,\d|$)/, ',$1$2');
}
And if you want to be fancy, you can format numbers with decimal points too:
while(num.match(/\d{4}(\,|\.)/)) {
num = num.replace(/(\d{3})(,\d|$|\.)/, ',$1$2');
}
Edit:
You can also do this with 2 regular expressions and no loop, splits, joins, etc:
num = num.replace(/(\d{1,2}?)((\d{3})+)$/, "$1,$2");
num = num.replace(/(\d{3})(?=\d)/g, "$1,");
The first regex puts a comma after the first 1 or 2 digits if the remaining number of digits is divisible by three. The second regex places a comma after every remaining group of 3 digits.
These won't work with decimals, but they work great for positive and negative integers.
Test output:
45
3,856
398,868,483,992
635
12,358,717,859,918,856
-1,388,488,184
This can be done in a single regex, no iteration required. If your browser supports ECMAScript 2018, you could simply use lookaround and just insert commas at the right places:
Search for (?<=\d)(?=(\d\d\d)+(?!\d))
and replace all with ,
In older versions, JavaScript doesn't support lookbehind, so that doesn't work. Fortunately, we only need to change a little bit:
Search for (\d)(?=(\d\d\d)+(?!\d))
and replace all with \1,
So, in JavaScript, that would look like:
result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
Explanation: Assert that from the current position in the string onwards, it is possible to match digits in multiples of three, and that there is a digit left of the current position.
This will also work with decimals (123456.78) as long as there aren't too many digits "to the right of the dot" (otherwise you get 123,456.789,012).
You can also define it in a Number prototype, as follows:
Number.prototype.format = function(){
return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
};
And then using it like this:
var num = 1234;
alert(num.format());
Credit: Jeffrey Friedl, Mastering Regular Expressions, 3rd. edition, p. 66-67
Someone mentioned that lookbehind isn't possible in Javascript RegExp. Here is a great page that explains how to use lookaround (lookahead and lookbehind).
http://www.regular-expressions.info/lookaround.html
underscore.string has a nice implementation.
I've amended it slightly to accept numeric strings.
function numberFormat (number, dec, dsep, tsep) {
if (isNaN(number) || number == null) return '';
number = parseFloat(number).toFixed(~~dec);
tsep = typeof tsep == 'string' ? tsep : ',';
var parts = number.split('.'), fnums = parts[0],
decimals = parts[1] ? (dsep || '.') + parts[1] : '';
return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
},
First reverse a character array, then add commas after every third number unless it's just before the end of the string or before a - sign. Then reverse the character array again and make it a string again.
function add_commas(numStr){
return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join('');
}