2010-02-12 2 views
30

Мне нужно отобразить отформатированный номер на веб-странице с помощью JavaScript. Я хочу отформатировать его так, чтобы в нужных местах были запятые. Как мне это сделать с регулярным выражением? Я получил, насколько что-то вроде этого:Регулярное выражение для форматирования чисел в JavaScript

myString = myString.replace(/^(\d{3})*$/g, "${1},"); 

... а потом понял, что это будет более сложным, чем я думаю (и выше регулярное выражение даже близко не к тому, что мне нужно). Я сделал несколько поисков, и мне сложно найти что-то, что работает для этого.

В принципе, я хочу, чтобы эти результаты:

  • 45 становится 45
  • 3856 становится 3856
  • 398868483992 становится 398,868,483,992

... Вы получаете идею.

+0

Большинство людей показало подходы, требующие итерации, но есть и фиксированные формы. –

+0

Если это проблема [XY] (http://meta.stackexchange.com/a/66378/150034), см. [Как напечатать номер с запятыми как разделители тысяч в JavaScript] (http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousand-separators-in-javascript) –

ответ

91

Это может быть сделано в одном регулярном выражении, ни итерации требуется. Если ваш браузер поддерживает ECMAScript 2018 года, вы могли бы просто использовать lookaround и просто вставить запятые в нужных местах:

Поиск по (?<=\d)(?=(\d\d\d)+(?!\d)) и заменить все с ,

В старых версиях, JavaScript не поддерживает назад ', так что не работает. К счастью, нам нужно только изменить немного:

Поиск по (\d)(?=(\d\d\d)+(?!\d)) и заменить все с \1,

Так, в JavaScript, который будет выглядеть так:

result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"); 

Объяснение: Утверждают, что из текущее положение в строке вперед, можно сопоставить цифры кратным трем и что цифра слева от текущей позиции.

Это также будет работать с десятичными знаками (123456.78), если не так много цифр «справа от точки» (в противном случае вы получите 123 456,789,012).

Вы также можете определить его в номер прототипа, а именно:

Number.prototype.format = function(){ 
    return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,"); 
}; 

, а затем использовать его как это:

var num = 1234; 
alert(num.format()); 

Авторы: Джеффри Friedl, Mastering Regular Expressions, 3rd. edition, стр. 66-67

+0

Спасибо! Именно то, что я искал. –

+2

Это великолепно, за исключением случаев, когда вы попадаете в поплавки: '0.1523234 -> 0.1.523,234' – 10basetom

+2

Забыл добавить ...если вы ожидаете, что поплавки будут меньше 1, затем добавьте условие, чтобы потребовать, чтобы число было больше 999, прежде чем выполнять замену (лучше, чем пытаться придумать более сложный RegExp для учета поплавков, меньших 1, которые могут закончиться будучи очень неэффективным). – 10basetom

0

попробовать что-то вроде этого:

function add_commas(numStr) 
{ 
    numStr += ''; 
    var x = numStr.split('.'); 
    var x1 = x[0]; 
    var x2 = x.length > 1 ? '.' + x[1] : ''; 
    var rgx = /(\d+)(\d{3})/; 
    while (rgx.test(x1)) { 
     x1 = x1.replace(rgx, '$1' + ',' + '$2'); 
    } 
    return x1 + x2; 
} 
0

Я думаю, что вы обязательно должны сделать несколько проходов для достижения этой цели с помощью регулярных выражений. Попробуйте следующее:

  1. Запустить регулярное выражение для одной цифры, а затем 3 цифры.
  2. Если это регулярное выражение совпадает, замените его на первую цифру, затем запятую, а затем на следующие 3 цифры.
  3. Повторяйте, пока (1) не найдете совпадений.
0

Сначала инвертируйте массив символов, затем добавьте запятые после каждого третьего номера, если только это не до конца строки или перед знаком -. Затем снова отмените массив символов и снова введите строку.

function add_commas(numStr){ 
    return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join(''); 
} 
+0

Вы избили меня до этого ... почти. См. Мой ответ за ту часть, которую вы пропустили. –

2

Если вы действительно хотите регулярное выражение, вы можете использовать два в время цикла:

while(num.match(/\d{4}/)) { 
    num = num.replace(/(\d{3})(,\d|$)/, ',$1$2'); 
} 

И если вы хотите быть фантазии, вы можете форматировать числа с десятичными точками тоже:

while(num.match(/\d{4}(\,|\.)/)) { 
    num = num.replace(/(\d{3})(,\d|$|\.)/, ',$1$2'); 
} 

Edit:

Вы также можете сделать это с 2 ре горловое выражение и нет петли, расколы, соединение, и т.д.:

num = num.replace(/(\d{1,2}?)((\d{3})+)$/, "$1,$2"); 
num = num.replace(/(\d{3})(?=\d)/g, "$1,"); 

Первого регулярного выражение ставит запятую после первых 1 или 2 цифр, если оставшееся количество цифр делятся на три. Второе регулярное выражение помещает запятую после каждой оставшейся группы из 3 цифр.

Они не будут работать с десятичными знаками, но они отлично работают для положительных и отрицательных целых чисел.

выходные Тест:

45 
3,856 
398,868,483,992 

635 
12,358,717,859,918,856 
-1,388,488,184 
0

итерация не нужно

function formatNumber(n, separator) { 
    separator = separator || ","; 

    n = n.toString() 
     .split("").reverse().join("") 
     .replace(/(\d{3})/g, "$1" + separator) 
     .split("").reverse().join(""); 

    // Strings that have a length that is a multiple of 3 will have a leading separator 
    return n[0] == separator ? n.substr(1) : n; 
} 

var testCases = [1, 45, 2856, 398868483992]; 
for (var i in testCases) { 
    if (!ns.hasOwnProperty(i)) { continue; } 
    console.info(testCases[i]); 
    console.log(formatNumber(testCases[i])); 
} 

Результаты

1 
1 

45 
45 

2856 
2,856 

398868483992 
398,868,483,992 
3

// Вы можете принять во внимание десятичные

Number.prototype.commas= function(){ 
var s= '', temp, 
num= this.toString().split('.'), n=num[0]; 
while(n.length> 3){ 
    temp= n.substring(n.length-3); 
    s= ','+temp+s; 
    n= n.slice(0, -3); 
} 
if(n) s= n+s; 
if(num[1]) s+='.'+num[1]; 
return s; 
} 

var n = 10000000000.34;

n.commas() = Возвращаемое значение: (строка) 10,000,000,000.34

11

Форматирование номера могут быть обработаны элегантно с одной строки кода.

Этот код расширяет объект Number; примеры использования приведены ниже.

Код:

Number.prototype.format = function() { 
    return this.toString().split(/(?=(?:\d{3})+(?:\.|$))/g).join(","); 
}; 

Как это работает

В регулярное выражение использует смотреть вперед, чтобы найти позиции в строке, где единственное, что справа от него есть один или больше группировок из трех чисел, до тех пор, пока не встретится ни десятичное, ни конец строки. .split() используется для разбиения строки в этих точках на элементы массива, а затем .join() объединяет эти элементы в строку, разделяемую запятыми.

Концепция нахождения позиций в строке, а не совмещение фактических символов, важна для разделения строки без удаления каких-либо символов.

Примеры использования:

var n = 9817236578964235; 
alert(n.format()); // Displays "9,817,236,578,964,235" 

n = 87345.87; 
alert(n.format()); // Displays "87,345.87" 

Конечно, код может быть легко расширен или изменен обрабатывать региональные аспекты. Например, здесь представлена ​​новая версия кода, которая автоматически определяет настройки локали и свопит использование запятых и периодов.

локали известно версия:

Number.prototype.format = function() { 

    if ((1.1).toLocaleString().indexOf(".") >= 0) { 
     return this.toString().split(/(?=(?:\d{3})+(?:\.|$))/g).join(","); 
    } 
    else { 
     return this.toString().split(/(?=(?:\d{3})+(?:,|$))/g).join("."); 
    } 
}; 

Если это не на самом деле нужно, я предпочитаю простоту первой версии, хотя.

+0

, что идеальная работа для меня также работает с этим регулярным выражением: 'replace (/ \ B (? = (\ D {3}) + (?! \ D))/g,", ");' –

+0

Это не хорошая практика для расширения собственных объектов в JavaScript. Когда вы расширяете объект, вы изменяете его поведение. Лучше просто написать его как простую функцию или определить свой собственный класс, который не вызовет неожиданного поведения с исходным объектом. – zgr024

+0

Ну, это философский и спорный аргумент. Хорошей новостью является то, что вы можете легко взять код в моем ответе выше и создать простую функцию, как вы сказали, вы предпочитаете. – Speednet

1

underscore.string имеет a nice implementation.

Я немного изменил его, чтобы принять числовые строки.

function numberFormat (number, dec, dsep, tsep) { 
    if (isNaN(number) || number == null) return ''; 

    number = parseFloat(number).toFixed(~~dec); 
    tsep = typeof tsep == 'string' ? tsep : ','; 

    var parts = number.split('.'), fnums = parts[0], 
    decimals = parts[1] ? (dsep || '.') + parts[1] : ''; 

    return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals; 
}, 
0

Brandon,

я не видел слишком много ответов, работающих регулярное выражение с десятичной точкой назад, так что я думал, что я мог бы звонить в.

Я задавался вопрос, есть ли польза элегантной на переписывание регулярного выражения для сканирования с задним вперед ...

function addCommas(inputText) { 
    // pattern works from right to left 
    var commaPattern = /(\d+)(\d{3})(\.\d*)*$/; 
    var callback = function (match, p1, p2, p3) { 
     return p1.replace(commaPattern, callback) + ',' + p2 + (p3 || ''); 
    }; 
    return inputText.replace(commaPattern, callback); 
} 

>> Fiddle Demo <<

Это означает любое десятичное место.

Смежные вопросы