2010-02-12 55 views
30

Necesito mostrar un número formateado en una página web usando JavaScript. Quiero formatearlo para que haya comas en los lugares correctos. ¿Cómo haría esto con una expresión regular? He llegado tan lejos como algo parecido a esto:Expresión regular para formatear números en JavaScript

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

... y luego se dio cuenta que esto sería más compleja de lo que pienso (y la expresión regular anterior es ni siquiera cerca a lo que necesito). He hecho algunas búsquedas y estoy teniendo dificultades para encontrar algo que funcione para esto.

Básicamente, quiero estos resultados:

  • 45 se convierte en 45
  • 3856 se convierte en 3856
  • 398868483992 convierte 398.868.483.992

... se entiende la idea.

+0

mayoría de las personas han mostrado enfoques que requieren repetición, pero no se fija formas también. –

+0

Si se trata de una [problema XY] (http://meta.stackexchange.com/a/66378/150034), véase [Cómo imprimir un número con comas como separadores de miles de JavaScript] (http://stackoverflow.com/preguntas/2901102/how-to-print-a-number-con-comas-como-miles-separadores-en-javascript) –

Respuesta

91

Esto se puede hacer en una sola expresión regular, no iteración requerido:

n.commas() = valor devueltos. Si su navegador es compatible con ECMAScript 2018, usted podría simplemente utilizar lookaround y basta con insertar comas en el sitio adecuado

búsqueda para (?<=\d)(?=(\d\d\d)+(?!\d)) y reemplazar todos con ,

En versiones anteriores, JavaScript no admite búsqueda hacia atrás, de manera que no funciona Afortunadamente, sólo tenemos que cambiar un poco:

Buscar (\d)(?=(\d\d\d)+(?!\d)) y reemplazar todos con \1,

Así, en JavaScript, que se vería así:

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

Explicación: afirmar que desde el posición actual en la cadena en adelante, es posible hacer coincidir los dígitos en múltiplos de tres, y que hay un dígito a la izquierda de la posición actual.

Esto también funcionará con decimales (123456.78) siempre que no haya demasiados dígitos "a la derecha del punto" (de lo contrario, obtendrá 123,456.789,012).

También puede definirlo en un prototipo número, de la siguiente manera:

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

Y a continuación, utilizando de esta manera:

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

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

+0

Gracias! Exactamente lo que estaba buscando. –

+2

Esta es brillante, excepto cuando usted entra en los flotadores: '0.1523234 -> 0.1,523,234' – 10basetom

+2

olvidó añadir ...si esperas que los flotadores sean más pequeños que 1, agrega una condición para exigir que el número sea mayor que 999 antes de hacer el reemplazo (es mejor que intentar generar un RegExp más complejo para tener en cuenta los flotadores menores a 1 que podrían terminar siendo muy ineficiente). – 10basetom

0

intentar algo como esto:

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

creo que necesariamente tendrían que hacer varias pasadas para lograr esto con expresiones regulares. Intente lo siguiente:

  1. Ejecute un regex de un dígito seguido de 3 dígitos.
  2. Si esa expresión regex coincide, reemplácela con el primer dígito, luego una coma, luego los siguientes 3 dígitos.
  3. Repita hasta que (1) no encuentre coincidencias.
0

Primero invierta una matriz de caracteres, luego agregue comas después de cada tercer número a menos que sea justo antes del final de la cadena o antes de un - signo. A continuación, invierta la matriz de caracteres nuevamente y vuelva a hacer una cadena.

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

me ganaste a ella ... casi. Mira mi respuesta para la parte que te perdiste. –

2

Si realmente desea una expresión regular, puede utilizar dos en un bucle while:

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

Y si quieres ser de lujo, puede dar formato a los números con puntos decimales también:

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

Editar:

también puede hacer esto con 2 re expresiones gular y ningún bucle, escisiones, se une, etc:

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

La primera expresión regular pone una coma después de los primeros 1 o 2 dígitos si el número restante de dígitos es divisible por tres. La segunda expresión regular coloca una coma después de cada grupo restante de 3 dígitos.

No funcionarán con decimales, pero funcionan muy bien para enteros positivos y negativos.

salida de prueba:

45 
3,856 
398,868,483,992 

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

iteración no es necesario

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

Resultados

1 
1 

45 
45 

2856 
2,856 

398868483992 
398,868,483,992 
3

// Es posible que desee tener en cuenta los decimales

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; (String) 10,000,000,000.34

11

formato a un número puede ser manejado elegantemente con una línea de código.

Este código amplía el objeto Número; ejemplos de uso se incluyen a continuación.

Código:

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

Cómo funciona

La expresión regular utiliza un preanálisis de encontrar posiciones dentro de la cadena en la que la única cosa a la derecha del mismo es uno o más agrupaciones de tres números, hasta que se encuentre un decimal o el final de la cadena. El .split() se utiliza para dividir la cadena en esos puntos en elementos de la matriz, y luego el .join() fusiona esos elementos en una cadena, separados por comas.

El concepto de encontrar posiciones dentro de la cadena, en lugar de coincidir con los caracteres reales, es importante para dividir la cadena sin eliminar ningún carácter.

ejemplos

de uso:

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

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

Por supuesto, el código puede ser fácilmente ampliar o modificar para manejar consideraciones locale. Por ejemplo, aquí hay una nueva versión del código que detecta automáticamente la configuración regional y cambia el uso de comas y puntos.

Locale-conscientes versión:

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

A menos que sea realmente necesario, yo prefiero la sencillez de la primera versión sin embargo.

+0

ese trabajo perfecto para mí también funciona esta expresión regular: 'reemplazar (/ \ B (? = (\ D {3}) + (?! \ D))/g,", ");' –

+0

No es una buena práctica para extender objetos nativos en JavaScript. Cuando extiende un objeto, modifica su comportamiento. Es mejor simplemente escribirlo como una función simple o definir su propia clase que no cause un comportamiento inesperado con el objeto original. – zgr024

+0

Bueno, ese es un argumento filosófico y discutible. La buena noticia es que puedes tomar fácilmente el código en mi respuesta anterior y crear una función simple, como dijiste que prefieres. – Speednet

1

underscore.string tiene a nice implementation.

He modificado ligeramente para aceptar cadenas numéricas.

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,

no vi demasiadas respuestas que trabajan la expresión regular desde el punto decimal hacia atrás, por lo que pensé que podría meter su cuchara.

Me preguntaba si hay algún beneficio elegante para volver a escribir la expresión regular para escanear desde la parte de atrás hacia adelante ...

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

Esto representa cualquier lugar decimal.

Cuestiones relacionadas