Enhancing regex of thousands separator?

独自空忆成欢 提交于 2019-12-04 02:09:46

问题


I saw this beautiful script to add thousands separator to js numbers:

function thousandSeparator(n, sep)
{
    var sRegExp = new RegExp('(-?[0-9]+)([0-9]{3})'),
        sValue = n + '';
    if(sep === undefined)
    {
        sep = ',';
    }
    while(sRegExp.test(sValue))
    {
        sValue = sValue.replace(sRegExp, '$1' + sep + '$2');
    }
    return sValue;
}

usage :

thousandSeparator(5000000.125, '\,') //"5,000,000.125"

However I'm having a trouble accepting the while loop.

I was thinking to change the regex to : '(-?[0-9]+)([0-9]{3})*' asterisk...

but now , how can I apply the replace statement ?

now I will have $1 and $2..$n

how can I enhance the replace func?

p.s. the code is taken from here http://www.grumelo.com/2009/04/06/thousand-separator-in-javascript/


回答1:


Your assumption

now i will have $1 and $2..$n

is wrong. You have two groups, because you have two sets of brackets.

    (-?[0-9]+)([0-9]{3})*
1.  ^^^^^^^^^^
2.            ^^^^^^^^^^

And then you repeat the second group. If it matches the second time, it overwrites the result of the first match, when it matches the third time, it overwrites ...

That means when matching is complete, $2 contains the value of the last match of that group.

First approach

(\d)(?=(?:[0-9]{3})+\b)

and replace with

$1,

See it on Regexr

It has the flaw that it does insert the comma also on the right of the dot. (I am working on it.)

Second approach

(\d)(?:(?=\d+(?=[^\d.]))(?=(?:[0-9]{3})+\b)|(?=\d+(?=\.))(?=(?:[0-9]{3})+(?=\.)))

and replace with

$1,

See it on Regexr

So now its getting a bit more complicated.

(\d)                   # Match a digit (will be reinserted)
(?:
    (?=\d+(?=[^\d.]))  # Use this alternative if there is no fractional part in the digit
    (?=(?:\d{3})+      # Check that there are always multiples of 3 digits ahead
    \b)                # Till a word boundary
    |                  # OR
    (?=\d+(?=\.))      # There is a fractional part
    (?=(?:\d{3})+      # Check that there are always multiples of 3 digits ahead
    (?=\.))            # Till a dot
)

Problem: does also match the fractional part if there is not the end of the string following.




回答2:


There is no need to use replace, you can just add toLocaleString instead:

console.log((5000000.125).toLocaleString('en'));

More information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString




回答3:


Here is an ugly script to contrast your beautiful script.

10000000.0001 .toString().split('').reverse().join('')
.replace(/(\d{3}(?!.*\.|$))/g, '$1,').split('').reverse().join('')

Since we don't have lookbehinds, we can cheat by reversing the string and using lookaheads instead.

Here it is again in a more palatable form.

function thousandSeparator(n, sep) {

    function reverse(text) {
        return text.split('').reverse().join('');
    }

    var rx = /(\d{3}(?!.*\.|$))/g;

    if (!sep) {
        sep = ',';
    }

    return reverse(reverse(n.toString()).replace(rx, '$1' + sep));

}



回答4:


Try this one:

result = subject.replace(/([0-9]+?)([0-9]{3})(?=.*?\.|$)/mg, "$1,$2");

Test here




回答5:


How about this one:

result = "1235423.125".replace(/\B(?=(\d{3})+(?!\d))/g, ',') //1,235,423.125


来源:https://stackoverflow.com/questions/10612286/enhancing-regex-of-thousands-separator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!