Регулярное выражение для форматирования чисел в JavaScript
Мне нужно отобразить отформатированный номер на веб-странице с помощью JavaScript. Я хочу отформатировать его так, чтобы в нужных местах были запятые. Как мне это сделать с регулярным выражением? Я получил что-то вроде этого:
myString = myString.replace(/^(\d{3})*$/g, "${1},");
... и затем понял, что это будет более сложным, чем я думаю (и регулярное выражение выше даже близко к тому, что мне нужно). Я сделал несколько поисков, и мне трудно найти что-то, что работает для этого.
В принципе, мне нужны эти результаты:
- 45 становится 45
- 3856 - 3,856
- 398868483992 - 398 868 483 992
... вы поняли идею.
Ответы
Ответ 1
Это может быть сделано в одном регулярном выражении, итерация не требуется. Если ваш браузер поддерживает ECMAScript 2018, вы можете просто использовать lookaround и просто вставлять запятые в нужных местах:
Найдите (?<=\d)(?=(\d\d\d)+(?!\d))
и замените все на ,
В старых версиях JavaScript не поддерживает "lookbehind", поэтому не работает. К счастью, нам нужно только немного измениться:
Найдите (\d)(?=(\d\d\d)+(?!\d))
и замените все на \1,
Итак, в JavaScript это будет выглядеть так:
result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
Объяснение: Утверждается, что начиная с текущей позиции в строке и далее можно сопоставлять цифры, кратные трем, и что от текущей позиции остается цифра.
Это также будет работать с десятичными числами (123456,78), если не слишком много цифр "справа от точки" (в противном случае вы получите 123 456 789 012).
Вы также можете определить его в прототипе Number следующим образом:
Number.prototype.format = function(){
return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
};
А затем, используя это так:
var num = 1234;
alert(num.format());
Фото: Джеффри Фридл, Овладение регулярными выражениями, 3-е место. издание, стр. 66-67
Ответ 2
Форматирование числа можно обрабатывать с помощью одной строки кода.
Этот код расширяет объект 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( "." );
}
};
Если это действительно необходимо, я предпочитаю простоту первой версии.
Ответ 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() = возвращаемое значение: (String) 10,000,000,000.34
Ответ 4
Если вы действительно хотите регулярное выражение, вы можете использовать два цикла while:
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:
Вы также можете сделать это с помощью двух регулярных выражений и без циклов, разделов, объединений и т.д.:
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
Ответ 5
Кто-то упомянул, что lookback в Javascript RegExp невозможно. Вот отличная страница, в которой объясняется, как использовать lookaround (lookahead и lookbehind).
http://www.regular-expressions.info/lookaround.html
Ответ 6
underscore.string имеет хорошую реализацию.
Я немного изменил его, чтобы принять числовые строки.
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;
},
Ответ 7
Попробуйте что-то вроде этого:
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;
}
Ответ 8
Я думаю, вам обязательно придется сделать несколько проходов, чтобы добиться этого с помощью регулярных выражений. Попробуйте следующее:
- Запустите регулярное выражение для одной цифры, а затем 3 цифры.
- Если это регулярное выражение совпадает, замените его на первую цифру, затем запятую, затем следующие 3 цифры.
- Повторяйте до тех пор, пока (1) не найдет совпадений.
Ответ 9
Сначала отмените массив символов, а затем добавьте запятые после каждого третьего номера, если это не до конца строки или перед знаком-. Затем снова измените массив символов и снова введите строку.
function add_commas(numStr){
return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join('');
}
Ответ 10
Итерация не требуется
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
Ответ 11
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 <
Это означает любое десятичное место.
Ответ 12
С учетом того, что Intl.NumberFormat
и Number.toLocaleString()
теперь есть для этой цели в JavaScript:
Другие ответы, использующие регулярные выражения, разбиваются на десятичные числа (хотя авторы, кажется, не знают этого, потому что они тестировали только с 1 или 2 десятичными знаками). Это связано с тем, что без "lookbehind" регулярные выражения JS не могут узнать, работаете ли вы с блоком цифр до или после десятичной точки. Это оставляет два способа решения этой проблемы с помощью регулярных выражений JS:
Знайте, есть ли десятичная точка в числе, и используйте различные регулярные выражения в зависимости от этого:
/(\d)(?=(\d{3})+$)/g
для целых чисел
/(\d)(?=(\d{3})+\.)/g
для десятичных чисел
Используйте два регулярных выражения, одно для соответствия десятичной части, а второе для замены.
function format(num) {
return num.toString().replace(/^[+-]?\d+/, function(int) {
return int.replace(/(\d)(?=(\d{3})+$)/g, '$1,');
});
}
console.log(format(332432432))
console.log(format(332432432.3432432))
console.log(format(-332432432))
console.log(format(1E6))
console.log(format(1E-6))