簡體   English   中英

帶有空格的自定義過濾器,因為千位分隔符不起作用

[英]Custom filter with white space as thousands separator is not working

我試圖編寫一個自定義過濾器來過濾應用程序中xxx xxx,xxx格式的數字。

這是我到目前為止編寫的函數:

var formatNumber = function(input, fractionSeparator, thousandsSeparator, fractionSize) {
    fractionSeparator = fractionSeparator || ',';
    thousandsSeparator = thousandsSeparator || ' ';
    fractionSize = fractionSize || 3;     
    var output = '', parts = [];

    input = input.toString();
    parts = input.split(".");
    output = parts[0].replace(/(\d{3})/g, ""+ thousandsSeparator +"$1").trim();
    if(parts.length>1){
        output += fractionSeparator;
        output += parts[1].substring(0, fractionSize);
    }       
    return output;
};

實際上,此功能對於某些數字而言效果理想,但在其他情況下會失敗,例如:

適用於以下數字:

  • 對於451.585478它打印451,585
  • 對於154455451.58它將打印154 455 451,58

這些示例失敗:

  • 對於54455451.58它將打印54455 451,58

  • 對於55451.58它打印55451,58

演示:

 var formatNumber = function(input, fractionSeparator, thousandsSeparator, fractionSize) { fractionSeparator = fractionSeparator || ','; thousandsSeparator = thousandsSeparator || ' '; fractionSize = fractionSize || 3; var output = '', parts = []; input = input.toString(); parts = input.split("."); output = parts[0].replace(/(\\d{3})/g, "" + thousandsSeparator + "$1").trim(); if (parts.length > 1) { output += fractionSeparator; output += parts[1].substring(0, fractionSize); } return output; }; console.log(formatNumber(154455451.58)); console.log(formatNumber(55451.58)); console.log(formatNumber(54455451.58)); 

我不知道這是怎么回事。 任何幫助將不勝感激。


編輯:

我終於使它工作了,問題出在我的Regex上,這是我用來格式化成千上萬個數字的最終正則表達式:

output = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator).trim();

這是最終代碼:

 var formatNumber = function(input, fractionSeparator, thousandsSeparator, fractionSize) { fractionSeparator = fractionSeparator || ','; thousandsSeparator = thousandsSeparator || ' '; fractionSize = fractionSize || 3; var output = '', parts = []; input = input.toString(); parts = input.split("."); output = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, thousandsSeparator).trim(); if (parts.length > 1) { output += fractionSeparator; output += parts[1].substring(0, fractionSize); } return output; }; console.log(formatNumber(154455451.58)); console.log(formatNumber(55451.58)); console.log(formatNumber(54455451.58)); 

問題在這里:

output = parts[0].replace(/(\d{3})/g, ""+ thousandsSeparator +"$1").trim();

您要在每3位數字前插入空格(我將在括號之間標記匹配項):

"(123)(456)78" --> "( 123)( 456)78"

然后修剪它-> "123 45678"

您的想法很好,但是您必須從右到左開始,這樣我將反轉parts[0]和替換項:

parts[0] = parts[0].split('').reverse().join('');
"12345678" --> "87654321"

parts[0] = parts[0].replace(/(\d{3})/g, "$1" + thousandsSeparator).trim();
"(876)(543)21" --> "(876 )(543 )21"

output = parts[0].split('').reverse().join('');
"876 543 21" --> "12 345 678"

您想要的輸出是哪個。 這是更新的代碼段:

 var formatNumber = function(input, fractionSeparator, thousandsSeparator, fractionSize) { fractionSeparator = fractionSeparator || ','; thousandsSeparator = thousandsSeparator || ' '; fractionSize = fractionSize || 3; var output = '', parts = []; input = input.toString(); parts = input.split("."); parts[0] = parts[0].split('').reverse().join(''); parts[0] = parts[0].replace(/(\\d{3})/g, "$1" + thousandsSeparator).trim(); output = parts[0].split('').reverse().join(''); if (parts.length > 1) { output += fractionSeparator; output += parts[1].substring(0, fractionSize); } return output; }; console.log(formatNumber(154455451.58)); console.log(formatNumber(55451.58)); console.log(formatNumber(54455451.58)); 

您可以在上分割您的號碼. 然后將其拆分並轉換為數組,可以使用array#maparray#filter來獲得一個新數組,其元素按3個塊進行分組,然后只需reversejoin backl

 const formatNumber = (num, fractionSeparator, thousandsSeparator, fractionSize) => { fractionSeparator = fractionSeparator || ','; thousandsSeparator = thousandsSeparator || ' '; fractionSize = fractionSize || 3; let [first, second] = num.toString().split('.'); let reversed = first.split('').reverse(); reversed = reversed.map((e,i) => i%fractionSize===0 ? reversed.slice(i,i+fractionSize).join('') :null) .filter(x => x) .reverse() .join(thousandsSeparator); return reversed + fractionSeparator + second; } console.log(formatNumber(154455451.58)); console.log(formatNumber(55451.58)); console.log(formatNumber(54455451.58)); 

這是另一種基於我曾經編寫的“貨幣格式化程序”方法的方法:

var sRegexFormatPattern = '^([^\\' + thousandsSeparator +
                          '\.]+)(\\d{3}[\\' + thousandsSeparator +
                          '\.]|\\d{3}$)';
var regexFormatPattern = new RegExp(sRegexFormatPattern);

while (regexFormatPattern.test(input)) {
    input = input.replace(regexFormatPattern, '$1' + thousandsSeparator + '$2');
}

讓我們從后到前分解正則表達式。

  • 第二個捕獲組( (\\\\d{3}[\\\\' + thousandsSeparator + '\\.]|\\\\d{3}$) )精確匹配3個數字和一個小數點( \\d{3}\\. ), \\d{3}\\THOUSANDS_SEPARATOR “ thousandsSeparator”( \\d{3}\\THOUSANDS_SEPARATOR )或字符串的末尾( \\d{3}$ )傳遞的字符。

  • 第一個捕獲組( ^([^\\\\' + thousandsSeparator + '\\.]+) )匹配所有不是的字符( 應該全部是數字...。您需要單獨檢查以確保這一點)小數點或作為“ thousandsSeparator”傳入的字符, 直到到達第二個捕獲組為止

注意:我在“ thousandsSeparator”之前添加了一個轉義斜杠,以防萬一有人在正則表​​達式中輸入了具有其他含義的內容,但即使如此,某些字符也可能在regex的執行中引起問題。 需要對其進行更多研究以使其更加安全。

只要能在值中找到這兩部分,它就會用“ thousandsSeparator”將其分解,然后再次檢查。 以“ 12345678.90”為例,迭代過程如下:

  • 12345 678. ---改變數量---> 12345 678.90
  • 12 345 678. ---改變數---> 12 345 678.90

該部分前后的所有內容或多或少都是您已經擁有的。 我還對字符串的“分數”部分的格式進行了細微調整,但其余部分幾乎相同( 請參見下面的完整JS代碼 )。

使用您的測試值,我得到:

- 451.585478 --->           451,585
- 154455451.58 ---> 154 455 451,58
- 54455451.58 --->   54 455 451,58
- 55451.58 --->          55 451,58

DEMO

 $("document").ready(function() { $(".formattingInput").on("change", function() { $("#formattedNumber").text(formatNumber( $("#unformattedNumberInput").val(), $("#fractionSeparator").val(), $("#thousandsSeparator").val(), $("#fractionSize").val() )); }); }); var formatNumber = function(input, fractionSeparator, thousandsSeparator, fractionSize) { fractionSeparator = fractionSeparator || ','; thousandsSeparator = thousandsSeparator || ' '; fractionSize = fractionSize || 3; var sRegexFormatPattern = '^([^\\\\' + thousandsSeparator + '\\.]+)(\\\\d{3}[\\\\' + thousandsSeparator + '\\.]|\\\\d{3}$)'; var regexFormatPattern = new RegExp(sRegexFormatPattern); while (regexFormatPattern.test(input)) { input = input.replace(regexFormatPattern, '$1' + thousandsSeparator + '$2'); } var parts = input.split('.'); if (parts.length > 1) { input = parts[0] + fractionSeparator + parts[1].substring(0, fractionSize); } return (input.length > 0) ? input : 'Please input a value in the "Number" field.'; }; 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div> <label for="unformattedNumberInput">Number: <input type="text" id="unformattedNumberInput" class="formattingInput" /></label><br /> <label for="thousandsSeparator">Thousands Separator: <input type="text" id="thousandsSeparator" class="formattingInput" /></label><br /> <label for="fractionSeparator">Fraction Separator: <input type="text" id="fractionSeparator" class="formattingInput" /></label><br /> <label for="fractionSize">Fraction Size: <input type="text" id="fractionSize" class="formattingInput" /></label><br /><br /> </div> <div> <strong>Result:</strong> <span id="formattedNumber">Please input a value in the "Number" field.</span> </div> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM