【问题标题】:Enhancing regex of thousands separator?增强千位分隔符的正则表达式?
【发布时间】:2012-05-16 05:01:49
【问题描述】:

我看到了这个漂亮的脚本来为 js 数字添加千位分隔符:

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;
}

用法:

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

但是我无法接受 while 循环

我正在考虑将正则表达式更改为:'(-?[0-9]+)([0-9]{3})*' asterisk...

但是现在,我该如何应用替换语句?

现在我将拥有$1$2..$n

如何增强替换功能?

附言代码取自这里http://www.grumelo.com/2009/04/06/thousand-separator-in-javascript/

【问题讨论】:

  • 顺便说一句,它在 5000000.125678 上失败 -> 5,000,000.125,678
  • 查看this question - 有一个链接to an example 告诉你如何做你正在尝试的事情。
  • @RobI 再次,它仍然有一个while循环。我认为可以找到更好的解决方案....(或没有)...:)
  • @Cylian 我认为我们需要积极向前看(-?[0-9]+)([0-9]{3})(?=\.) 但它不起作用......我的意思是 - 只替换右边有一个点的数字。

标签: javascript regex performance separator


【解决方案1】:

不用replace,直接加toLocaleString即可:

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

更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString

【讨论】:

  • 谢谢。非常好。除非我在标签中写了 [regex],否则我会选择这个答案
  • 另一个人在他的回答中付出了很多努力,所以无论如何他都应该接受;) - 但你真的不应该为此使用正则表达式,本机方式更好(并且更容易理解) .
  • 你可以肯定我会从现在开始使用它:)
  • @luschen 我觉得自己像个菜鸟,因为不知道这个。我觉得我已经写了很多次正则表达式来做到这一点,但基于我在这篇文章上的情况,我也总是每次都清楚地把它搞砸,不得不再次谷歌搜索。这个我可能不会忘记……加上本地化,耶!
【解决方案2】:

你的假设

现在我将有 $1 和 $2..$n

错了。你有两组,因为你有两组括号。

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

然后你重复第二组。如果第二次匹配,则覆盖第一次匹配的结果,当匹配第三次时,覆盖...

这意味着当匹配完成时,$2 包含该组的最后一个匹配的值。

第一种方法

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

替换为

$1,

it on Regexr

它的缺点是它确实在点的右侧也插入了逗号。 (我正在努力。)

第二种方法

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

替换为

$1,

it on Regexr

所以现在它变得有点复杂了。

(\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
)

问题: 如果后面没有字符串的结尾,也会匹配小数部分。

【讨论】:

  • 你好,是的,你说得对。但正如你所看到的,我面临两个问题。它确实考虑了右侧 123.1234567 中的数字,我需要摆脱 while 循环
  • @RoyiNamir 我扩展了我的答案,但到目前为止只针对第二个问题。第一个仍然是个问题。
  • @stema 看起来不错,如果你能把右边的那部分修好,我刚刚和自己打赌输了。
  • @ggg 你将拥有自己 5 美元
  • @RoyiNamir 我想我找到了解决方案,请测试一下。
【解决方案3】:

这是一个丑陋的脚本来对比你漂亮的脚本。

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

由于我们没有lookbehinds,我们可以通过反转字符串并使用lookaheads来作弊。

这又是一种更可口的形式。

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));

}

【讨论】:

  • 我需要下载winrar才能使用这个代码吗?大声笑(很长)...:) 谢谢
  • @RoyiNamir 你觉得清理后的版本怎么样?反转字符串不适合你吗?
  • 我在 jsperf 中对其进行了测试,它的速度非常慢(与主样本相比 - 右边的逗号不起作用..)我需要先修复我的解决方案:只从右二:去掉while循环。
  • @RoyiNamir 很好,这确实解决了这两个问题,但我不怀疑像这样反转字符串很慢......我认为环顾四周也可能很慢。很想看看其他人的想法。
  • 我认为我们需要先进行第一阶段...如何使其仅适用于左侧数字...
【解决方案4】:

这个怎么样:

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

【讨论】:

  • 试试这个:"1235423.12342345".replace(/\B(?=(\d{3})+(?!\d))/g, ',') // "1,235,423.12,342,345"
【解决方案5】:

试试这个:

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

测试here

【讨论】:

  • 不错,但它也将逗号放在小数点右侧:(
  • 123456.134'.replace(/([0-9]+?)([0-9]{3})(?=.*?\.|$)/mg, "$1,$2") 产量:"1,23456.134"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多