¿Hay algún truco para agregar comas a grandes números?

201

¿Hay alguna manera de que los rieles impriman un número con comas?

Por ejemplo, si tengo un número 54000000.34, puedo ejecutar <% = number.function%>, que imprimiría "54,000,000.34"

¡Gracias!

Encadenar
fuente

Respuestas:

353

Quieres el number_with_delimitermétodo. Por ejemplo:

<%= number_with_delimiter(@number, :delimiter => ',') %>

Alternativamente, puede usar el number_with_precisionmétodo para asegurarse de que el número siempre se muestre con dos decimales de precisión:

<%= number_with_precision(@number, :precision => 2, :delimiter => ',') %>
John Topley
fuente
55
@Mo Es un método de ayuda de vista. Debería poder usarlo desde un módulo incluyéndolo ActionView::Helpers::NumberHelperdentro del módulo.
John Topley
9
Creo que, por defecto, el delimitador es una coma, por lo que no necesitará pasar esa opción en este caso.
Deekor
3
Debe dejar el delimitador desactivado para que la configuración regional actual pueda decidir qué usar. Esto permite que las configuraciones regionales que usan períodos para delimitadores se muestren correctamente en lugar de poner lo que considerarían un punto decimal entre miles. Ver la respuesta de coloradoblue a continuación.
Kyle Heironimus
1
Sintaxis de Rails 4: <% = number_with_precision (@number, precision: 0, delimiter: ',')%>
Choylton B. Higginbottom
2
Cuidado: number_with_delimiteres demasiado complejo y realmente lento, con enormes profundidades de pilas de llamadas. Suele i18nser capaz de formatear cualquier número conocido por la humanidad y las civilizaciones extraterrestres (o tal vez solo para elegir uno ,o .para dígitos decimales, incluso si lo especifica como argumento). Asigna miles de objetos (por lo que sus patrones de rendimiento son complejos y difíciles de perfilar). Considere simplemente usar expresiones regulares si no necesita admitir diferentes formas de formatear números dependiendo de la configuración regional.
kolen
133

Para cualquiera que no use rieles:

number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
pguardiario
fuente
2
Agradable. Y su respuesta parece ser minuciosa (solo una fracción de segundo más de un millón de iteraciones) más rápida que el enfoque presentado aquí :number.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
user664833
¿Puedes explicar lo que está pasando aquí? number.to_s.reverse.gsub (/ (\ d {3}) (? = \ d) /, '\\ 1,'). reverse
Stephen Nguyen
77
Claro, invierte la cadena, luego agrega una coma después de cualquier secuencia de 3 dígitos que también es seguida por otro dígito, luego la invierte de nuevo.
pguardiario
1
@renosis: ahora entiendo a qué te refieres, esto es para formatear moneda. Entonces 2 decimales, no 7.
pguardiario
2
@pguardiario ¿Cuál es el \ extra en \\ 1? no es \1suficiente? Gracias.
butterywombat
31

La forma directa de hacer esto, con o sin Rails , es:

require 'active_support/core_ext/numeric/conversions'

12345.to_s(:delimited)      # => "12,345"
12345.6789.to_s(:delimited) # => "12,345.6789"

Para obtener más opciones, consulte Extensiones principales de soporte activo - Numérico - Formateo .

chocolateboy
fuente
1
Y con esta inclusión también puedes usarla ActiveSupport::NumberHelper.number_to_delimited. Esta respuesta merece muchos más votos a favor.
Ulysse BN
30

Sí, use el NumberHelper . El método que está buscando es number_with_delimiter .

 number_with_delimiter(98765432.98, :delimiter => ",", :separator => ".")
 # => 98,765,432.98
PatrikAkerstrand
fuente
24

Si desea agregar comas fuera de las vistas y no desea incluir algunos módulos, puede usar el método number_to_delimited (versión de rails> = 4.02). Por ejemplo:

#inside anywhere
ActiveSupport::NumberHelper.number_to_delimited(1000000) # => "1,000,000"
Alexander Ryhlitsky
fuente
19

Si lo está haciendo mucho pero también para su información porque no está implícito en lo anterior, Rails tiene valores predeterminados razonables para el number_with_delimitermétodo.

#inside controller or view
number_with_delimiter(2444323.4)
#=> 2,444,323.30

#inside console
helper.number_with_delimiter(233423)
#=> 233,423

No es necesario proporcionar el valor del delimitador si lo está haciendo de la manera más típica.

coloradoblue
fuente
Esto tiene el beneficio adicional de usar la configuración regional actual. Esto es realmente importante en las aplicaciones internacionales, ya que algunas configuraciones regionales usan comas para separador decimal y punto para miles.
Kyle Heironimus
16

Una mejor manera para aquellos que no usan rieles que maneja decimales:

parts = number.to_s.split('.')
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
parts.join('.')

Si desea un delimitador diferente, cambie el último ',' en la expresión regular.

Como bonificación, así es como funciona la expresión regular:

  • gsub reemplaza todo lo que coincide con la expresión regular con el segundo parámetro pasado a gsub. En este caso eso es \\1. \\1se convierte \1cuando se evalúa cuál coincide con el primer grupo de captura en la expresión regular. En esta expresión regular que es (\d).
  • (\d)(?=(\d\d\d)+)coincide con un dígito seguido de 1 o más grupos de 3 dígitos. El primer grupo de padres es nuestro \1grupo de captura, el segundo sería \2. Si lo dejáramos así, obtendríamos: 123456.gsub!(/(\d)(?=(\d\d\d)+)/, "\\1,") #=> 1,2,3,456Esto se debe a 1234 coincidencias, 2345 coincidencias y 3456 coincidencias, por lo que colocamos una coma después del 1, el 2 y el 3.
  • Al agregar (?! \ D) estamos haciendo coincidir todo lo que viene antes que no preceda a un dígito, por lo que (\d)(?=(\d\d\d)+(?!\d))significa que coincide con un dígito seguido de 3 dígitos que no son seguidos por un dígito. La razón por la que esto funciona es que gsub seguirá reemplazando cosas que coincidan con la cadena. Si solo íbamos a reemplazar el primer partido, entonces para un número como 123456789 obtendríamos 123456,789. Como 123456,789 todavía coincide con nuestra expresión regular, obtenemos 123,456,789.

Aquí es donde obtuve el código: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper.rb#L298-L300

Y aquí es donde aprendí acerca de lo que está sucediendo en esa expresión regular: http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm

fxfilmxf
fuente
funciona de {{ value | round | replace: "(\d)(?=(\d\d\d)+(?!\d))", "$1," | prepend: "$" }}
maravilla
2

Otra solución que no usa Helpers: formatee con 2 decimales y luego reemplace. por

puts(("%.2f" % 2.5666).gsub('.',','))
>> 2,57
Nino van Hooff
fuente
1
Creo que la pregunta era acerca de las comas para la agrupación de dígitos , no la coma como separador decimal intergral de parte / fracción que su respuesta logra. (como explica el enlace de la wiki, debido a la larga confusión, los estándares internacionales ahora recomiendan espacios solo para la agrupación de dígitos)
Beni Cherniavsky-Paskin
1

Puedes usar métodos de ActiveSupport

Por ejemplo:

ActiveSupport::NumberHelper::number_to_currency(10000.1234,{precision: 2,unit: ''})

Le Duc Duy
fuente
1
  def add_commas(numstring)
    correct_idxs = (1..100).to_a.select{|n| n % 6 == 0}.map{|n| n - 1}
     numstring.reverse.chars.join(",").chars.select.with_index{|x, i| i.even? || correct_idxs.include?(i)}.join.reverse
  end

Este era mi camino en rubí

Edición adicional: Básicamente, agrega todas las comas entre los números y solo selecciona aquellas en las que el índice + 1% 6

Me imaginé que las comas hasta 100 estaban bien, pero si quieres un número súper largo simplemente haz 100 un número más alto

Justin Cox
fuente
0

nueva sintaxis

number_with_delimeter(@number, delimeter: ",")

Si desea usar el delimitador por dinero, puede hacerlo

number_to_currency(@number)

esto agregará $también. Si estás usando moneygema, entonces puedes hacer

Money.new(@number,"USD").format

Esto también lo pondrá $.

número_con_delimitador

dinero rubí

number_to_currency

gsumk
fuente
0

Lo siguiente hace el truco para el delimitador y la precisión ( API ref ).

ActiveSupport::NumberHelper.number_to_rounded(1234.532, delimiter: ',', precision: 1) 

(o solo desde las vistas number_to_rounded, no es necesario el sufijo)

HTH

Hertzel Guinness
fuente
-1

para la gente de javascript

function numberWithDelimiter(value) {
    return (value+"").split("").reverse().join("").replace(/(\d{3})(?=\d)/g, '$1,').split("").reverse().join("")
}

:)

aqm
fuente