使用replace和正则表达式应用货币格式

时间:2018-03-13 16:20:57

标签: javascript regex

我正在尝试理解一些代码,其中数字转换为货币格式。因此,如果您有16.9,则转换为16.90美元。代码的问题在于,如果您的金额超过1,000美元,它只返回1美元,超过2,000美元的金额返回2美元等等。数百美元的金额显示正常。

这是功能:

var _formatCurrency = function(amount) {
    return "$" + parseFloat(amount).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,')
};

(分号在括号之后的原因是因为此函数本身就是另一个函数中的一个语句。该函数与此讨论无关。)

我发现最初将代码放在那里的人发现它在某个地方但没有完全理解它并且没有测试这个特定的场景。我自己没有处理正则表达式。我不仅试图解决它,而且要了解它现在是如何工作的。

这是我发现的。打开括号后的反斜杠和g之前的反斜杠之间的代码是模式。 g表示全局搜索。 \d表示数字,(?=\d{3})+\.似乎表示查找3位数加上小数点。不过,我不确定我是否有这个权利,因为如果这是正确的,那么它是否应该忽略像5.4这样的数字?这很好。另外,我不确定'$1,'的用途。在我看来它应该被放置在数字所在的位置,但不会将所有数字改为$ 1?另外,为什么1之后会有逗号?

4 个答案:

答案 0 :(得分:0)

假设您仅使用USD,那么这应该适合您作为正则表达式的替代方法。我还包括一些测试来验证它是否正常工作。



var test1 = '16.9';
var test2 = '2000.5';
var test3 = '300000.23';
var test4 = '3000000.23';

function stringToUSD(inputString) {
  const splitValues = inputString.split('.');
    
  const wholeNumber = splitValues[0].split('')
    .map(val => parseInt(val))
    .reverse()
    .map((val, idx, arr) => idx !== 0 && (idx + 1) % 3 === 0 && arr[idx + 1] !== undefined ? `,${val}` : val)
    .reverse()
    .join('');
    
  return parseFloat(`${wholeNumber}.${splitValues[1]}`).toFixed(2);
}

console.log(stringToUSD(test1));
console.log(stringToUSD(test2));
console.log(stringToUSD(test3));
console.log(stringToUSD(test4));




答案 1 :(得分:0)

模式无效,您对该功能的理解不正确。此函数以标准美国货币格式化数字,以下是它的工作原理:

  1. parseFloat()函数将字符串值转换为十进制数。
  2. toFixed(2)函数将十进制数舍入小数点后的2位数。
  3. replace()函数用于添加数千个算子(即每3个数字后面的逗号)。模式不正确,因此这是一个建议的修复/(\d)(?=(\d{3})+\.)/g,这是它的工作原理:
    • (\d)捕获一个数字。
    • (?=(\d{3})+\.)被称为前瞻,它确保上面捕获的数字有一组3位(\d{3})或更多+,后跟小数点{{1}之后跟一个小数点。
    • \.标志/修饰符是全局应用模式,即整个金额。
    • 替换g会将模式替换为第一个捕获的组$1,,在我们的例子中是数字$1(因此在技术上会替换数字以确保我们不会' t丢失替换中的数字)后跟逗号(\d)。就像我说的那样,这只是添加千位分隔符。
  4. 以下是一些建议修复的测试。请注意,它适用于数字和字符串:

    ,

答案 2 :(得分:0)

关于你的评论

我希望只编辑正则表达式,以便它能正常工作。

你目前正在使用的正则表达式显然不适合你,所以我认为你应该考虑替代品,即使它们不太相似,并且

尽量保持代码更改

可以理解,但有时最好使用比使用紧凑和象形文字更大更易读的代码。

回到公司:

我假设你得到一个字符串作为参数,这个字符串只由数字组成,在最后的1或2个数字之前可能有也可能没有点。像

这样的东西
//input     //intended output
1           $1.00
20          $20.00
34.2        $34.20
23.1        $23.10
62516.16    $62,516.16
15.26       $15.26
4654656     $4,654,656.00
0.3         $0.30

我会让你预先检查(假设的)非<,> 2.2。 | .6 | 4.8.1 | 4.856 |的

提议的解决方案:

var _formatCurrency = function(amount) {
    amount = "$" + amount.replace(/(\d)(?=(\d{3})+(\.(\d){0,2})*$)/g, '$1,');

    if(amount.indexOf('.') === -1)
        return amount + '.00';

    var decimals = amount.split('.')[1];

    return decimals.length < 2 ? amount + '0' : amount;
};

正则表达式崩溃:

  
      
  • (\d):匹配一位数字。括号将事物分组,以便在需要时进行引用。

  •   
  • (?=(\d{3})+(\.(\d){0,2})*$)。现在这家伙。从头到尾:

         
        
    • $:匹配字符串的结尾。这是允许您从末尾而不是从头开始匹配的,这对于添加逗号非常方便。
    •   
    • (\.(\d){0,2})*:此部分处理点和小数。 \.与点匹配。 (\d){0,2}匹配0,1或2位数(小数)。 *表示整个组都可以为空。
    •   
    • ?=(\d{3})+\d{3}完全匹配3位数。 +表示至少发生一次。最后?=匹配主表达式之后的组,而不将其包含在结果中。在这种情况下,它一次需要三个数字(从结束开始记住吗?)并在更换时将它们留在结果之外。
    •   
    • g:全局匹配和替换整个字符串。
    •   
  •   
  • 替换为$1,:这是替换引用的已捕获组的方式,在这种情况下,所需组的数字为 1 。由于模式将匹配位置 3n + 1 (从结束或点开始)中的每个数字,并且捕获它在组编号 1 (\d)),然后用$1,替换该捕获符将在每次捕获后有效地添加逗号。
  •   

试试并请反馈。

此外,如果你还没有(你也没有给我提供足够强调的格式),请真正按照this site

的建议调查Taplar

答案 3 :(得分:0)

好的,我想向所有回答的人道歉。我做了一些进一步的跟踪,发现JSON调用带来的数量实际上有一个逗号,所以它只是解析第一个数字。当我认为那里没有逗号时,我在代码中查找错误的位置。我非常感谢大家的意见,并希望你不会因为在整个练习之前没有抓住这一点而认为太糟糕。如果不出意外,至少我现在知道正则表达式是如何运作的,所以我将来可以利用它。现在我只需要删除该逗号。

祝你有美好的一天!