preface
In scenarios involving large numbers, such as number of people, amount of money, etc., we often need to place the numbers in thousandths and separate them with commas, which is easier to read.
Such as
123456789
Copy the code
If it’s in the thousandths
123.456.789
Copy the code
Comparing these two kinds, we must choose the second one, which is convenient to read.
implementation
So how do you do that?
Typically, regular expressions are used
function formatNumber(num) {
const reg = /(\d)(? =(\d{3})+$)/g
return num.toString().replace(reg, '$1')
}
formatNumber(12345678) / / "12345678"
formatNumber(8765432188) / / "8765432188"
Copy the code
Test passed.
But this is based on integers. If your number has a decimal point, the result is as follows
formatNumber(1234.5678) / / 1234.5, "678"
Copy the code
The expectation is “1,234.5678”, you don’t need to do thousandths of the decimal part, you just need to do thousandths of the integer part,
Actual is 1234.5 “, 678”
So you need to optimize the regex.
function formatNumber(num) {
const reg = /(\d)(? =(\d{3})+\.) /g
return num.toString().replace(reg, '$1')
}
formatNumber(1234.5678) / / "1234567"
formatNumber(1234) / / "1234"
Copy the code
As you can see from the example above,
It works if the number has a decimal point
However, if the number has no decimal point, this re will not work, so you need to combine the two re’s to support integers and decimals
function formatNumber(num) {
num = num.toString()
let reg = num.indexOf('. ') > -1 ? /(\d)(? =(\d{3})+\.) /g : /(\d)(? =(\d{3})+$)/g
return num.replace(reg, '$1')
}
formatNumber(1234.5678) / / "1234567"
formatNumber(1234) // "1,234"
Copy the code
The following is the regular /(\d)(? = (\ d {3}) + $)/g and/(\ d)? =(\d{3})+\.) /g for analysis:
- This regular is mainly used to exploit
d{3}
Every three digits are matched, followed by a comma, and so on. - The re is added here
$
and.
In order to give priority to the following three bits, if the beginning is less than three bits, it will not be processed. - A regular expression is also used here
(? =pattern)
, the term is calledZero width assertion
, or also calledPositive positive pre-check
.
Implement thousandths of separation, the core point is this, let’s talk about the regular expression.
Zero width assertion (positive affirmative precheck)
(? =pattern), which matches the regular expression but does not get the match. The next match will start at that location.
It will be easier to understand with examples:
var regA = / the answer? =cp3)/
console.log('the answer cp3'.match(regA)) // [" answer "]
var regB = /cp3(? =cp3)/g
console.log('cp3cp3cp3cp3'.match(regB)) // ["cp3", "cp3", "cp3"]
Copy the code
The first example shows that the answer cp3 is matched, but only the answer is retrieved, not cp3
In the second example, you can see that cp3cp3 is matched, and only CP3 is retrieved. The next match starts with the second cp3, and so on, and finally outputs three CP3.
Combined with the thousandth separation example above, because we used the zero-width assertion, since it will start at that position again next time, this results in every number being matched up to the end
let reg = /(\d)(? =(\d{3})+)/g
'1234567890'.replace(reg, (match,$1, $2, index, str) = > {
console.log(match,$1, $2, index, str)
return $1 + ', '}) output1 1 890 0 1234567890The output2 2 678 1 1234567890The output3 3 789 2 1234567890The output4 4 890 3 1234567890The output5 5 678 4 1234567890The output6 6 789 5 1234567890The output7 7 890 6 1234567890return"1,2,3,4,5,6,7,890"
Copy the code
So we add $or to the zero width assertion. To constrain, restrict the preference to match the end, the beginning less than 3 bits will not be processed
let reg = /(\d)(? =(\d{3})+$)/g
'1234567890'.replace(reg, (match,$1, $2, index, str) = > {
console.log(match,$1, $2, index, str)
return $1 + ', '}) output1 1 890 0 1234567890The output4 4 890 3 1234567890The output7 7 890 6 1234567890return"1234567890"
Copy the code
There will be no problem in that case.
conclusion
The above is the use of re to achieve a thousand – digit separation summary
Complete code:
function formatNumber(num) {
num = num.toString()
let reg = num.indexOf('. ') > -1 ? /(\d)(? =(\d{3})+\.) /g : /(\d)(? =(\d{3})+$)/g
return num.replace(reg, '$1')}Copy the code