Esiste un trucco per rotaie per l'aggiunta di virgole a grandi numeri?


201

C'è un modo per fare in modo che le rotaie stampino un numero con virgole?

Ad esempio, se ho un numero 54000000.34, posso eseguire <% = number.function%>, che stampa "54.000.000.34"

Grazie!

Risposte:


353

Vuoi il number_with_delimitermetodo. Per esempio:

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

In alternativa, è possibile utilizzare il number_with_precisionmetodo per assicurarsi che il numero sia sempre visualizzato con due decimali di precisione:

<%= number_with_precision(@number, :precision => 2, :delimiter => ',') %>

5
@Mo È un metodo di supporto alla vista. Dovresti essere in grado di usarlo da un modulo includendolo ActionView::Helpers::NumberHelperall'interno del modulo.
John Topley,

9
Per impostazione predefinita, credo che il delimitatore sia una virgola, quindi in questo caso non è necessario passare tale opzione.
Deekor,

3
Dovresti lasciare il delimitatore spento in modo che la locale corrente possa decidere cosa usare. Ciò consente ai locali che utilizzano i periodi per i delimitatori di essere visualizzati correttamente anziché inserire un valore decimale tra migliaia. Vedi la risposta coloradoblue di seguito.
Kyle Heironimus,

1
Sintassi di Rails 4: <% = number_with_precision (@number, precisione: 0, delimitatore: ',')%>
Choylton B. Higginbottom

2
Attenzione: number_with_delimiterè eccessivamente complesso e molto lento, con enormi profondità di stack di chiamate. Usa i18nper essere in grado di formattare qualsiasi numero noto all'umanità e alle civiltà extraterrestri (o forse solo per scegliere una ,o .per le cifre decimali, anche se lo specifichi come argomento). Alloca migliaia di oggetti (quindi i suoi modelli di prestazioni sono complessi e difficili da profilare). Prendi in considerazione l'utilizzo di regexps se non hai bisogno di supportare diversi modi per formattare i numeri a seconda delle impostazioni locali.
Kolen,

133

Per chiunque non usi le rotaie:

number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse

2
Bello. E la tua risposta sembra essere minuziosamente (solo una frazione di secondo oltre un milione di iterazioni) più veloce dell'approccio presentato qui :number.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
user664833

puoi spiegare cosa sta succedendo qui? number.to_s.reverse.gsub (/ (\ d {3}) (? = \ d) /, '\\ 1,'). reverse
Stephen Nguyen,

7
Certo, inverte la stringa, quindi aggiunge una virgola dopo ogni sequenza di 3 cifre seguita anche da un'altra cifra, quindi la inverte indietro.
pguardiario,

1
@renosis - Capisco cosa intendi ora, questo è per la formattazione della valuta. Quindi 2 decimali, non 7.
pguardiario

2
@pguardiario Qual è il extra \ per nel \\ 1? non è \1sufficiente? Grazie.
Butterywombat,



24

Se si desidera aggiungere virgole al di fuori delle viste e non si desidera includere alcuni moduli, è possibile utilizzare il metodo number_to_delimited (versione rotaie> = 4.02). Per esempio:

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

19

Se lo stai facendo molto ma anche FYI perché non è implicito da quanto sopra, Rails ha impostazioni predefinite ragionevoli per il number_with_delimitermetodo.

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

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

Non è necessario fornire il valore del delimitatore se lo stai facendo nel modo più tipico.


Ciò ha l'ulteriore vantaggio di utilizzare la locale corrente. Questo è molto importante nelle app internazionali poiché alcune localizzazioni usano la virgola per il decimale e il punto per il separatore delle migliaia.
Kyle Heironimus,

16

Un modo migliore per coloro che non usano le guide che gestiscono i decimali:

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

Se vuoi un delimitatore diverso, modifica l'ultimo ',' nella regex.

Per bonus, ecco come funziona il regex:

  • gsub sostituisce tutto ciò che corrisponde a regex con il secondo parametro passato a gsub. In questo caso \\1. \\1diventa \1quando valutato che corrisponde al primo gruppo di acquisizione nella regex. In questa regex che è(\d) .
  • (\d)(?=(\d\d\d)+)corrisponde a una cifra seguita da 1 o più gruppi di 3 cifre. Il primo set di parentesi è il nostro \1gruppo di acquisizione, il secondo sarebbe \2. Se solo lo lasciassimo, otterremmo: 123456.gsub!(/(\d)(?=(\d\d\d)+)/, "\\1,") #=> 1,2,3,456 Questo perché 1234 partite, 2345 partite e 3456 partite quindi inseriamo una virgola dopo 1, 2 e 3.
  • Aggiungendo il (?! \ D) ci sono corrispondenti tutto ciò che viene prima di quella non precede una cifra così (\d)(?=(\d\d\d)+(?!\d))mezzo corrispondano una cifra seguita da 3 cifre che non è seguita da una cifra. Il motivo per cui funziona è che gsub continuerà a sostituire le cose che corrispondono alla stringa. Se avessimo solo sostituito la prima partita, per un numero come 123456789 avremmo 123456.789. Dato che 123456.789 corrispondono ancora al nostro regex, otteniamo 123.456.789.

Ecco dove ho ottenuto il codice: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper.rb#L298-L300

Ed ecco dove ho imparato cosa sta succedendo in quella regex: http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm


funziona come un incantesimo, soprattutto in lang template liquido:{{ value | round | replace: "(\d)(?=(\d\d\d)+(?!\d))", "$1," | prepend: "$" }}
Kukunin

2

Un'altra soluzione che non utilizza gli helper: formatta con 2 cifre decimali e quindi sostituisci. di,

puts(("%.2f" % 2.5666).gsub('.',','))
>> 2,57

1
Credo che la domanda riguardasse le virgole per il raggruppamento delle cifre , non la virgola come separatore decimale parte intergrale / parte frazione ottenuto dalla tua risposta. (come spiega quel link wiki, a causa della confusione di lunga data, gli standard internetionali ora raccomandano spazi solo per il raggruppamento delle cifre)
Beni Cherniavsky-Paskin

1

Puoi usare metodi da ActiveSupport

Per esempio:

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


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

Questa era la mia strada nel rubino

Modifica aggiunta: Fondamentalmente aggiunge tutte le virgole tra i numeri e seleziona solo quelle in cui l'indice + 1% 6

Ho pensato che le virgole fino a 100 andassero bene, ma se vuoi un numero molto lungo, fai 100 un numero più alto


0

nuova sintassi

number_with_delimeter(@number, delimeter: ",")

Se si desidera utilizzare il delimitatore per denaro, è possibile farlo

number_to_currency(@number)

questo aggiungerà $anche. Se stai usando moneygem, allora puoi farlo

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

Questo metterà anche $.

number_with_delimiter

soldi rubini

number_to_currency


0

Di seguito sono riportati i suggerimenti sia per il delimitatore che per la precisione (riferimento API ).

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

(o solo dalle visualizzazioni number_to_rounded, non è necessario il suffisso)

HTH


-1

per gente di javascript

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

:)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.