The so-called numerical form is to add a comma between every three digits starting from single digits. For example, "10,000". To address this requirement, I initially wrote a function like this:
The code copy is as follows:
// Method 1
function toThousands(num) {
var result = [ ], counter = 0;
num = (num || 0).toString().split('');
for (var i = num.length - 1; i >= 0; i--) {
counter++;
result.unshift(num[i]);
if (!(counter % 3) && i != 0) { result.unshift(','); }
}
return result.join('');
}
The execution process of method one is to convert the numbers into strings, break them into an array, and then start from the end, insert the elements in the array to the beginning of the new array (result). Every time an element is inserted, the counter counts the number (add 1). When the counter is a multiple of 3, a comma is inserted, but be careful that there is no comma required at the beginning (when i is 0). Finally, the result is obtained by calling the join method of the new array.
The method was clearer and easier to understand, and it was also used in the project for a while. But intuition tells me that it's not performing well.
Method 2 - String version of Method 1
The code copy is as follows:
// Method 2
function toThousands(num) {
var result = '', counter = 0;
num = (num || 0).toString();
for (var i = num.length - 1; i >= 0; i--) {
counter++;
result = num.charAt(i) + result;
if (!(counter % 3) && i != 0) { result = ',' + result; }
}
return result;
}
Method 2 is an improved version of Method 1. It does not break strings into arrays, and always operates on strings.
Method 3 - Loop matches the three numbers at the end
The code copy is as follows:
// Method 3
function toThousands(num) {
var num = (num || 0).toString(), re = //d{3}$/, result = '';
while ( re.test(num) ) {
result = RegExp.lastMatch + result;
if (num !== RegExp.lastMatch) {
result = ',' + result;
num = RegExp.leftContext;
} else {
num = '';
break;
}
}
if (num) { result = num + result; }
return result;
}
Method 3 is a completely different algorithm. The three numbers at the end are matched through a regular expression loop. Each time the match is matched, the comma and the matching content are inserted at the beginning of the result string, and then the matching target (num) is assigned to the content that has not yet matched (RegExp.leftContext). In addition, please note:
1. If the number of digits is a multiple of 3, the last match must be three numbers, but there is no need to add a comma before the first three numbers;
2. If the number of bits of a number is not a multiple of 3, then the num variable will definitely have 1 to 2 numbers left in the end. After the loop, the remaining numbers should be inserted at the beginning of the result string.
Although Method Three reduces the number of loops (three characters are processed at a time), the consumption is increased to a certain extent due to the use of regular expressions.
Method 4 - String version of Method 3
The code copy is as follows:
// Method 4
function toThousands(num) {
var num = (num || 0).toString(), result = '';
while (num.length > 3) {
result = ',' + num.slice(-3) + result;
num = num.slice(0, num.length - 3);
}
if (num) { result = num + result; }
return result;
}
In fact, the function of intercepting the last three characters can be achieved through the slice, substr or substring method of the string type. This avoids regular expressions.
Method 5 - Combination and convergence method
The code copy is as follows:
// Method 5
function toThousands(num) {
var num = (num || 0).toString(), temp = num.length % 3;
switch (temp) {
case 1:
num = '00' + num;
break;
case 2:
num = '0' + num;
break;
}
return num.match(//d{3}/g).join(',').replace(/^0+/, '');
}
First, make up the number of digits into multiples of 3, cut them into groups of every three numbers through regular expressions, then add commas through the join method, and finally remove the complement 0.
Method 6 - Lazy Method
The code copy is as follows:
// Method 6
function toThousands(num) {
return (num || 0).toString().replace(/(/d)(?=(?:/d{3})+$)/g, '$1,');
}
I always feel that this formatting can be made by a regular expression replacement, but I need to use assertions and other writing methods, but I am not familiar with this part. After Googled it, I found such a regular expression, which is probably the shortest implementation of the code.
Test results
| number | Time spent on 5000 times (ms) | |||||
|---|---|---|---|---|---|---|
| Method 1 | Method 2 | Method 3 | Method 4 | Method 5 | Method 6 | |
| 1 | 4 | 1 | 3 | 1 | 14 | 2 |
| 10 | 14 | 1 | 3 | 0 | 7 | 2 |
| 100 | 12 | 1 | 2 | 4 | 5 | 3 |
| 1000 | 13 | 2 | 3 | 2 | 9 | 5 |
| 10000 | twenty one | 4 | 3 | 1 | 6 | 3 |
| 100000 | twenty one | 3 | 2 | 1 | 5 | 6 |
A strong comparison between Method 1 and Method 2 shows that the efficiency of string operations is much higher than that of array operations; the test results of Method 6 tell us that the length of the code has nothing to do with the performance. Method 4 has the best comprehensive performance (but why does num decrease when 100 num is really unsolvable), the main reason is:
1. Compare methods 1 and 2, operate 3 characters instead of 1 character each time to reduce the number of loops;
2. Comparison methods 3, 5, and 6, without using regular expressions, reducing consumption.
Finally, I chose Method Four as the final optimization solution. Readers can comment if they have better implementation methods or suggestions.