Подтвердить что ты не робот

Регулярное выражение для форматирования чисел в JavaScript

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

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

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

В принципе, мне нужны эти результаты:

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

... вы поняли идею.

4b9b3361

Ответ 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:

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

    • /(\d)(?=(\d{3})+$)/g для целых чисел
    • /(\d)(?=(\d{3})+\.)/g для десятичных чисел
  2. Используйте два регулярных выражения, одно для соответствия десятичной части, а второе для замены.

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