Formatting numbers with commas


#1

I needed to format numbers with commas to make it more human
readable. Here’s how I did it.

def commify(number)
c = { :value => “”, :length => 0 }
r = number.to_s.reverse.split("").inject© do |t, e|
iv, il = t[:value], t[:length]
iv += ‘,’ if il % 3 == 0 && il != 0
{ :value => iv + e, :length => il + 1 }
end
r[:value].reverse!
end

Am interested in how many better ways there are to do it. Maybe even
a one liner …

– G.


#2

Guido S. wrote:

I needed to format numbers with commas to make it more human
readable. Here’s how I did it.

def commify(number)
c = { :value => “”, :length => 0 }
r = number.to_s.reverse.split("").inject© do |t, e|
iv, il = t[:value], t[:length]
iv += ‘,’ if il % 3 == 0 && il != 0
{ :value => iv + e, :length => il + 1 }
end
r[:value].reverse!
end

Am interested in how many better ways there are to do it. Maybe even
a one liner …

– G.

Here’s how I did it recently

num_with_commas =
number.to_s.reverse.gsub(/(\d{3})/,"\1,").chomp(",").reverse

Note that this will run into trouble if you have decimal points in it.
If you do, just cut off that part of the string and paste it back on
after you add the commas.

_Kevin


#3

On 1/24/06, Guido S. removed_email_address@domain.invalid wrote:

end
r[:value].reverse!

end

Am interested in how many better ways there are to do it. Maybe even a one
liner …

– G.

Check out NumberHelper in the API, it is a one liner:

number_with_delimiter(number, delimiter=",")

Formats a number with a delimiter. Example:

number_with_delimiter(12345678) => 12,345,678

[ hide source <javascript:toggleSource(‘M000363_source’)> ]

# File 

vendor/rails/actionpack/lib/action_view/helpers/number_helper.rb,
line 75
75: def number_with_delimiter(number, delimiter=",")
76: number.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/,
“\1#{delimiter}”)
77: end


#4

Guido S. wrote:

r[:value].reverse!

end

Am interested in how many better ways there are to do it. Maybe even a
one liner …
Depends what you count as one line :slight_smile:

def commify(v)
(s=v.to_s;x=s.length;s).rjust(x+(3-(x%3))).scan(/.{3}/).join(’,’).strip
end

Doesn’t work for negative numbers, though, but it’s quite fun… This
works, but is boring:

v.to_s.reverse.gsub(/(\d{3})(?=\d)/x,’\1,’).reverse


#5

The gsub approach is much nicer. Exactly what I was looking for. Thanks!

– G.


#6

On Jan 24, 2006, at 6:38 PM, Alex Y. wrote:

def commify(v)
(s=v.to_s;x=s.length;s).rjust(x+(3-(x%3))).scan(/.{3}/).join
(’,’).strip
end

I tried to mess with the regex, /.{3}/ to get it to ignore '.'s and
stuff following it, but that breaks the neat slicing in three’s …
unless x=s.length - s.scan(/…*/) …

So far, only the gsub approach works for floating point numbers …
but only if they have two or fewer digits past the ‘.’ …

irb(main):024:0> v = 1000000.0101
=> 1000000.0101
irb(main):025:0> v.to_s.reverse.gsub(/(\d{3})(?=\d)/x,’\1,’).reverse
=> “1,000,000.0,101”
irb(main):026:0>

So which is gonna win when doing the floats? gsub or rjust+scan ? :slight_smile:

I like both approaches …

– G.


#7

You can ignore this question for my purposes, though it might be of
general interest. I decided after seeing how SQLite datatype support
worked that I would see if I could get MySQL working anyway. To my
amazement, it came right up and did what I expected. So I’m back
using MySQL and thus able to follow the Agile book much more easily.

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
Dan S.
Technology Visionary - Technology Assessment - Documentation
“Looking at technology from every angle”
http://www.eclecticity.com


#8

After a good bit of hassle, I finally got Locomotive working on my OS
X box. Because it seems more comfortable with SQLite than with MySQL,
I’m using the former for the moment in preparation for the Rails
Studio in Pasadena this week.

I ran into a tiny issue which I’d like to understand better.

I created a SQLite table in the usual way:

sqlite3 depot_developer

Then I created a text table-creating file called create_products.sql
and stuck in the db folder of the Rails app’s directory.

Then I switched to the db directory, launched sqlite3 and instructed
it to .read the newly created SQL file. It appeared to work
flawlessly. Indeed, when I ask SQLite3 for the .tables, I see the
products table there. Cool.

Then I tried to create the scaffold for the project and I got an error:

   create    test/fixtures/products.yml
    error  Before updating scaffolding from new DB schema, try

creating a table for your model (Product)

I tried again with the same result.

So I deleted the depot_development database and then looked at the
Locomotive video where I saw that it created a new database with an
initial table by:

sqlite3 depot_development < create_products.sql

This seemed kind of strange to me but I tried it and then ran the
scaffolding generation and it worked fine (or at least reported no
error).

Can anyone tell me why this happened? My big concern at the moment is
that the next time I need to add a table to this depot_development
database I don’t want to lose my existing table by using the “<”
syntax rather than reading the table-creation SQL inside SQLite.

Thanks.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
Dan S.
Technology Visionary - Technology Assessment - Documentation
“Looking at technology from every angle”
http://www.eclecticity.com