Gibt es einen Rails-Trick, um großen Zahlen Kommas hinzuzufügen?

201

Gibt es eine Möglichkeit, dass Schienen eine Zahl mit Kommas ausdrucken?

Wenn ich beispielsweise eine Nummer 54000000.34 habe, kann ich <% = number.function%> ausführen, wodurch "54.000.000.34" gedruckt wird.

Vielen Dank!

Jess
quelle

Antworten:

353

Sie wollen die number_with_delimiterMethode. Beispielsweise:

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

Alternativ können Sie die number_with_precisionMethode verwenden, um sicherzustellen, dass die Zahl immer mit zwei Dezimalstellen angezeigt wird:

<%= number_with_precision(@number, :precision => 2, :delimiter => ',') %>
John Topley
quelle
5
@Mo Es ist eine Ansichtshilfemethode. Sie sollten es von einem Modul aus verwenden können, indem Sie es ActionView::Helpers::NumberHelperin das Modul aufnehmen.
John Topley
9
Ich glaube, dass das Trennzeichen standardmäßig ein Komma ist, sodass Sie diese Option in diesem Fall nicht übergeben müssen.
Deekor
3
Sie sollten das Trennzeichen weglassen, damit das aktuelle Gebietsschema entscheiden kann, was verwendet werden soll. Auf diese Weise können Gebietsschemas, die Punkte für Trennzeichen verwenden, ordnungsgemäß angezeigt werden, anstatt einen Dezimalpunkt zwischen Tausenden zu setzen. Siehe die Antwort von coloradoblue unten.
Kyle Heironimus
1
Rails 4-Syntax: <% = number_with_precision (@number, Genauigkeit: 0, Trennzeichen: ',')%>
Choylton B. Higginbottom
2
Achtung: number_with_delimiterist zu komplex und sehr langsam, mit enormen Tiefen von Anrufstapeln. Es wird verwendet i18n, um alle Zahlen zu formatieren, die der Menschheit und außerirdischen Zivilisationen bekannt sind (oder um entweder eine ,oder .eine Dezimalstelle zu wählen , selbst wenn Sie sie als Argument angeben). Es weist Tausende von Objekten zu (daher sind seine Leistungsmuster komplex und schwer zu profilieren). Verwenden Sie nur reguläre Ausdrücke, wenn Sie nicht unterschiedliche Methoden zum Formatieren von Zahlen je nach Gebietsschema unterstützen müssen.
Kolen
133

Für alle, die keine Schienen benutzen:

number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
pguardiario
quelle
2
Nett. Und Ihre Antwort scheint minutiös (nur ein Bruchteil einer Sekunde über eine Million Iterationen) schneller zu sein als der hier vorgestellte Ansatz :number.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
user664833
Können Sie erklären, was hier los ist? number.to_s.reverse.gsub (/ (\ d {3}) (? = \ d) /, '\\ 1,'). reverse
Stephen Nguyen
7
Sicher, es kehrt die Zeichenfolge um, fügt dann nach einer Folge von 3 Ziffern ein Komma hinzu, auf das auch eine weitere Ziffer folgt, und kehrt sie dann zurück.
Pguardiario
1
@renosis - Ich verstehe, was Sie jetzt meinen, dies ist für die Formatierung der Währung. Also 2 Dezimalstellen, nicht 7.
pguardiario
2
@pguardiario Was ist das Extra \ für in der \\ 1? ist nicht \1ausreichend? Vielen Dank.
Butterwombat
31

Der direkte Weg, dies mit oder ohne Schienen zu tun , ist:

require 'active_support/core_ext/numeric/conversions'

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

Weitere Optionen finden Sie unter Active Support Core-Erweiterungen - Numerisch - Formatierung .

Schokoladenjunge
quelle
1
Und mit dieser Aufnahme können Sie auch verwenden ActiveSupport::NumberHelper.number_to_delimited. Diese Antwort verdient viel mehr positive Stimmen.
Ulysse BN
30

Ja, verwenden Sie den NumberHelper . Die Methode, nach der Sie suchen, ist number_with_delimiter .

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

Wenn Sie Kommas außerhalb von Ansichten hinzufügen und einige Module nicht einschließen möchten, können Sie die Methode number_to_delimited verwenden (Rails-Version> = 4.02). Beispielsweise:

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

Wenn Sie viel tun, aber auch zu Ihrer Information, weil dies nicht durch das oben Gesagte impliziert wird, hat Rails sinnvolle Standardeinstellungen für die number_with_delimiterMethode.

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

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

Sie müssen den Begrenzerwert nicht angeben, wenn Sie dies auf die typischste Weise tun.

coloradoblue
quelle
Dies hat den zusätzlichen Vorteil, dass das aktuelle Gebietsschema verwendet wird. Dies ist in internationalen Apps sehr wichtig, da einige Ländereinstellungen Komma als Dezimalzahl und Punkt für Tausendertrennzeichen verwenden.
Kyle Heironimus
16

Ein besserer Weg für diejenigen, die keine Schienen verwenden, die Dezimalstellen verarbeiten:

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

Wenn Sie ein anderes Trennzeichen möchten, ändern Sie das letzte ',' in der Regex.

Für den Bonus funktioniert der Regex folgendermaßen:

  • gsub ersetzt alles, was mit dem regulären Ausdruck übereinstimmt, durch den zweiten Parameter, der an gsub übergeben wird. In diesem Fall ist das \\1. \\1wird \1bei der Auswertung, was mit der ersten Erfassungsgruppe in der Regex übereinstimmt. In dieser Regex ist das (\d).
  • (\d)(?=(\d\d\d)+)stimmt mit einer Ziffer überein, gefolgt von einer oder mehreren Gruppen von 3 Ziffern. Die erste Gruppe von Parens ist unsere \1Fanggruppe, die zweite wäre \2. Wenn wir es einfach so belassen würden, würden wir bekommen: 123456.gsub!(/(\d)(?=(\d\d\d)+)/, "\\1,") #=> 1,2,3,456 Dies liegt daran, dass 1234 Übereinstimmungen, 2345 Übereinstimmungen und 3456 Übereinstimmungen, also setzen wir ein Komma nach der 1, der 2 und der 3.
  • Durch Hinzufügen des (?! \ D) (\d)(?=(\d\d\d)+(?!\d))stimmen wir mit allem überein , was vor einer Ziffer steht. Dies bedeutet, dass eine Ziffer gefolgt von 3 Ziffern, auf die keine Ziffer folgt, übereinstimmt. Der Grund, warum dies funktioniert, ist, dass gsub weiterhin Dinge ersetzt, die mit der Zeichenfolge übereinstimmen. Wenn wir nur das erste Spiel ersetzen würden, würden wir für eine Zahl wie 123456789 123456.789 erhalten. Da 123456.789 immer noch mit unserer Regex übereinstimmt, erhalten wir 123.456.789.

Hier habe ich den Code erhalten: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper.rb#L298-L300

Und hier habe ich erfahren, was in dieser Regex vor sich geht: http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm

fxfilmxf
quelle
funktioniert wie ein Zauber, vor allem in Liquid Vorlage lang:{{ value | round | replace: "(\d)(?=(\d\d\d)+(?!\d))", "$1," | prepend: "$" }}
Kukunin
2

Eine andere Lösung, die keine Helfer verwendet: Formatieren Sie mit 2 Dezimalstellen und ersetzen Sie diese. durch ,

puts(("%.2f" % 2.5666).gsub('.',','))
>> 2,57
Nino van Hooff
quelle
1
Ich glaube, die Frage bezog sich auf Kommas für die Zifferngruppierung und nicht auf Kommas als Dezimaltrennzeichen zwischen Teil- und Bruchteil, das Ihre Antwort erreicht. (Wie dieser Wiki-Link erklärt, empfehlen Internet-Standards aufgrund der langjährigen Verwirrung nur Leerzeichen für die Gruppierung von Ziffern)
Beni Cherniavsky-Paskin
1

Sie können Methoden von verwenden ActiveSupport

Beispielsweise:

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

Le Duc Duy
quelle
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

Das war mein Weg in Rubin

Addition bearbeiten: Grundsätzlich werden alle Kommas zwischen den Zahlen hinzugefügt und nur diejenigen ausgewählt, bei denen der Index + 1% 6 ist

Ich dachte, die Kommas bis zu 100 wären in Ordnung, aber wenn Sie eine super lange Zahl wollen, machen Sie einfach 100 zu einer höheren Zahl

Justin Cox
quelle
0

neue Syntax

number_with_delimeter(@number, delimeter: ",")

Wenn Sie Delimeter für Geld verwenden möchten, können Sie dies tun

number_to_currency(@number)

Dies wird auch hinzufügen $. Wenn Sie moneyEdelsteine ​​verwenden, können Sie dies tun

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

Dies wird auch setzen $.

number_with_delimiter

Rubingeld

number_to_currency

gsumk
quelle
0

Im Folgenden wird der Trick sowohl für das Trennzeichen als auch für die Genauigkeit ausgeführt ( API-Referenz ).

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

(oder nur aus Ansichten number_to_rounded, keine Notwendigkeit für das Suffix)

HTH

Hertzel Guinness
quelle
-1

für Javascript Leute

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

:) :)

aqm
quelle