web-dev-qa-db-fra.com

Expression régulière pour la mise en forme des nombres en JavaScript

Je dois afficher un numéro formaté sur une page Web à l'aide de JavaScript. Je veux le formater afin qu'il y ait des virgules aux bons endroits. Comment pourrais-je faire cela avec une expression régulière? Je suis arrivé à quelque chose comme ça:

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

... et ensuite réalisé que ce serait plus complexe que je ne le pense (et la regex ci-dessus est même pas proche de ce dont j'ai besoin). J'ai fait des recherches et j'ai du mal à trouver quelque chose qui fonctionne pour ça.

En gros, je veux ces résultats:

  • 45 devient 45 
  • 3856 devient 3 856
  • 398868483992 devient 398,868,483,992

...vous avez eu l'idée.

36
Brandon Montgomery

Cela peut être fait en une seule expression rationnelle, aucune itération requise. Si votre navigateur prend en charge ECMAScript 2018, vous pouvez simplement utiliser lookaround et insérer des virgules aux bons endroits:

Recherchez (?<=\d)(?=(\d\d\d)+(?!\d)) et remplacez tout par ,

Dans les versions antérieures, JavaScript ne prend pas en charge la recherche, ce qui ne fonctionne pas. Heureusement, il suffit de changer un peu:

Recherchez (\d)(?=(\d\d\d)+(?!\d)) et remplacez tout par \1,

Donc, en JavaScript, cela ressemblerait à:

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

Explication: Vérifiez que, à partir de la position actuelle dans la chaîne, il est possible de faire correspondre les chiffres par multiples de trois et qu'il existe un chiffre à gauche de la position actuelle.

Cela fonctionnera également avec les décimales (123456.78) tant qu'il n'y aura pas trop de chiffres "à droite du point" (sinon, vous obtenez 123,456.789.012).

Vous pouvez également le définir dans un prototype numérique, comme suit:

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

Et puis l'utiliser comme ça:

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

Crédit: Jeffrey Friedl, Mastering Regular Expressions, 3rd. édition , p. 66-67

106
Tim Pietzcker

Le formatage d’un nombre peut être traité avec élégance avec une ligne de code.

Ce code étend l'objet Number; Des exemples d'utilisation sont inclus ci-dessous.

Code:

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

Comment ça marche

L'expression régulière utilise une prévision pour trouver des positions dans la chaîne où la seule chose à sa droite est un ou plusieurs groupements de trois nombres, jusqu'à ce qu'une décimale ou la fin de la chaîne soit rencontrée. La .split() est utilisée pour casser la chaîne à ces points en éléments de tableau, puis la .join() fusionne ces éléments dans une chaîne, séparés par des virgules.

Le concept de recherche de positions dans la chaîne, plutôt que de faire correspondre les caractères réels, est important afin de scinder la chaîne sans supprimer aucun caractère.

Exemples d'utilisation:

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

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

Bien entendu, le code peut facilement être étendu ou modifié pour prendre en compte les paramètres régionaux. Par exemple, voici une nouvelle version du code qui détecte automatiquement les paramètres régionaux et remplace l'utilisation de virgules et de points.

Version compatible avec les paramètres régionaux:

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( "." );
    }
};

À moins que ce soit vraiment nécessaire, je préfère cependant la simplicité de la première version.

14
Speednet

// Vous voudrez peut-être prendre en compte les décimales

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 () = valeur renvoyée: (chaîne) 10 000 000 000,34

3
kennebec

Si vous voulez vraiment une regex, vous pouvez utiliser la boucle two in a while:

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

Et si vous voulez être chic, vous pouvez aussi formater des nombres avec des points décimaux:

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

Modifier:

Vous pouvez également le faire avec 2 expressions régulières et aucune boucle, scission, jointure, etc.:

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

La première expression régulière met une virgule après les 1 ou 2 premiers chiffres si le nombre de chiffres restant est divisible par trois. La deuxième expression régulière place une virgule après chaque groupe restant de 3 chiffres.

Celles-ci ne fonctionneront pas avec les nombres décimaux, mais elles fonctionnent très bien pour les entiers positifs et négatifs.

Test de sortie:

45
3,856
398,868,483,992

635
12,358,717,859,918,856
-1,388,488,184
2
Jeff B

Quelqu'un a mentionné que regarder en arrière n'est pas possible dans Javascript RegExp. Voici une superbe page qui explique comment utiliser lookaround (lookahead and lookbehind).

http://www.regular-expressions.info/lookaround.html

1
Robusto

underscore.string a une implémentation de Nice .

Je l'ai légèrement modifié pour accepter les chaînes numériques.

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;
},
1
mpen

L'itération n'est pas nécessaire

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]));
}

Résultats

1
1

45
45

2856
2,856

398868483992
398,868,483,992
0
Justin Johnson

Brandon,

Je n'ai pas vu trop de réponses utiliser la regex à partir de la virgule décimale, alors j'ai pensé que je pourrais intervenir.

Je me demandais s'il y avait un avantage élégant à réécrire l'expression rationnelle pour numériser à partir de l'arrière ...

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

Cela représente une décimale quelconque.

0
Levi Beckman

Essayez quelque chose comme ça: 

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
Seth

Je pense que vous devrez nécessairement faire plusieurs passes pour y parvenir avec des expressions régulières. Essayez ce qui suit:

  1. Exécuter une expression régulière pour un chiffre suivi de 3 chiffres.
  2. Si cette expression régulière correspond, remplacez-la par le premier chiffre, puis par une virgule, puis par les 3 prochains chiffres.
  3. Répéter jusqu'à ce que (1) ne trouve aucune correspondance.
0
Ryan Brunner

Commencez par inverser un tableau de caractères, puis ajoutez une virgule après chaque troisième nombre, sauf si c'est juste avant la fin de la chaîne ou avant le signe -. Puis inversez à nouveau le tableau de caractères et faites-en une chaîne à nouveau.

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