I am trying to take the following number:
423523420987
And convert it to this:
4235 2342 0987
It doesn't necessarily have to be an integer either. In fact, I would prefer it to be a string.
You can use String::gsub with a regular expression:
=> 'abcdefghijkl'.gsub(/.{4}(?=.)/, '\0 ')
'abcd efgh ijkl'
class String
def in_groups_of(n, sep=' ')
chars.each_slice(n).map(&:join).join(sep)
end
end
423523420987.to_s.in_groups_of(4) # => '4235 2342 0987'
423523420987.to_s.in_groups_of(5, '-') # => '42352-34209-87'
To expand on #Mark Byer's answer and #glenn mcdonald's comment, what do you want to do if the length of your string/number is not a multiple of 4?
'1234567890'.gsub(/.{4}(?=.)/, '\0 ')
# => "1234 5678 90"
'1234567890'.reverse.gsub(/.{4}(?=.)/, '\0 ').reverse
# => "12 3456 7890"
If you are looking for padded zeros in case you have less than 12 or more than 12 numbers this will help you out:
irb(main):002:0> 423523420987.to_s.scan(/\d{4}/).join(' ')
=> "4235 2342 0987"
irb(main):008:0> ('%d' % 423523420987).scan(/\d{4}/).join(' ')
=> "4235 2342 0987"
Loop through each digit and if the loop index mod 4 = 0 then place a space.
Modulus in Ruby
Related
How do I parse out a string in rails? I have my form for submitting a height. Example: 5'9 I want the comma parsed and the 59 saved within the database
If you want to ignore anything other than numbers, use this regex
"5'9".gsub(/\D/, '')
# => "59"
"5 9".gsub(/\D/, '')
# => "59"
"5 feet 9 inches".gsub(/\D/, '')
# => "59"
'5" 9'.gsub(/\D/, '')
# => "59"
Regex Explanation: \D stands for any character other than a digit.
There are a number of ways to do this. If you want to just remove the quote, you could use:
"5'9".gsub "'", ""
#=> "59"
or
"5'9".split("'").join("")
#=> "59"
If you want to save the 5 and the 9 in different attributes, you could try:
a = "5'9".split("'")
object.feet = a[0]
object.inches = a[1]
If you want to remove everything but the numbers you could use a regex:
"5'9".gsub /[^\d]/, ""
#=> "59"
If you have a different requirement, please update the question to add more detail.
You want to look at the sub or gsub methods
height.gsub! "'", ''
Where sub replaces the first instance, and gsub replaces all instances and you could even do this on the model:
before_validation :remove_apostrophes # or before_save
protected
def remove_apostrophes
self.property.gsub! "'", ''
end
I have the following stuff in my DB:
postcode
66
2
34
25
54
98
1
14
5
39
37
Now what is a nice way to group this records by only the first digit (and count it)?
So the hash output is sth. like this:
1 => 2
5 => 2
9 => 1
3 => 3
etc
Model.group(:postcode).count
would be the standard query here to consider both digits. Is there any addition needed?
Or should I straight modify the DB and cut the 2nd digit (I don't want that).
Get all the postcode from db as an Array
array = Model.pluck(:postcode)
Group by first digit, map values array to get count
Hash[ array.group_by {|n| n.to_s[0] }.map {|k, v| [k.to_i, v.size] }]
grouped_by = ['65', '15', '11', '29','4','56'].group_by { |n| n[0] }
# {"6"=>["65"], "1"=>["15", "11"], "2"=>["29"], "4"=>["4"], "5"=>["56"]}
grouped_by.map{ |k,v| {k => v.count} }
# [{"6"=>1}, {"1"=>2}, {"2"=>1}, {"4"=>1}, {"5"=>1}]
It first groups by the first digit and then maps over the resulting hash and replaces the values with the count of the values.
For a pure SQL implementation:
Model.group("SUBSTR(CAST(postcode as CHAR), 1, 1)").count
How can i round in ruby only higher, and so, that 2 last numbers are null?
For exapmle
4233.000001 to 4300
52825 to 52900
627444 to 627500
111999 to 112000
?
Now i can round only in mathematic-rules via round(-2), but how to do only higher, and only with 2 null's on the end?
You should use ceil
def my_round a
(a / 100.0).ceil * 100
end
my_round 4233.000001 # => 4300
my_round 52825 # => 52900
my_round 627444 # => 627500
my_round 111999 # => 112000
working off Sergio's answer, you could mix a module in to the actual Numeric object for a more general solution:
module RoundsUp
def round_up(ndigits)
pow_ten = 10 ** -ndigits
(self / pow_ten.to_f).ceil * pow_ten
end
end
then
mynumeric = 262.33
mynumeric.extend(RoundsUp)
mynumeric.round_up(-2) #=> 300
and you've got a method that behaves like the normal round for any number of digits
Suppose I have the number 1.29999. I want to just have 1.2 without the trailing 9s. Note, I don't want it to round to 1.3. How do I do this? I know there's the number helper, but I can't seem to get this working outside of a view. Any ideas?
For instance, number_with_precision 111.2345, :precision => 2 does not work if I just put it in a normal model function.
Thanks!
Another approach is to multiply by 100, truncate, then divide by 100.0:
$ irb --simple-prompt
>> (1.29999999*100).truncate/100.0
=> 1.29
Making it a method:
>> def truncate_to_two (x)
>> (x * 100).truncate/100.0
>> end
=> nil
>> truncate_to_two 6342.899
=> 6342.89
>> truncate_to_two -322.11892
=> -322.11
>> truncate_to_two 244.9342
=> 244.93
It's rudimentary, but you can do use string manipulation instead of math to do it. Example:
x = 1.29999
truncated = x.to_s.match(/(\d+\.\d{2})/)[0] # assumes the format "n.nn" with 2 or more digits of precision; the regex can be expanded to handle more cases
You can always include ActionView::Helpers::NumberHelper in your model to get access to the helpers.
I'm storing a decimal in rails and I need to have it display as a currency as such:
11.1230 => "$11.123"
11.1000 => "$11.10"
11.0100 => "$11.01"
11.1234 => "$11.1234"
Any easy way to do this?
def pad_number( number, min_decimals=2 )
s = "%g" % number
decimals = (s[/\.(\d+)/,1] || "").length
s << "." if decimals == 0
s << "0"*[0,min_decimals-decimals].max
end
puts [ 11.123, 11.1, 11.01, 11.1234, 11 ].map{ |n| pad_number(n) }
#=> 11.123
#=> 11.10
#=> 11.01
#=> 11.1234
#=> 11.00
Edit: Looks like this is Rails 3 specific, as Rails 2's number_with_precision method doesn't include the strip_insignificant_zeros option:
You can pass some options to number_to_currency (a standard Rails helper):
number_to_currency(11.1230, :precision => 10, :strip_insignificant_zeros => true)
# => "$11.123"
You need to provide a precision in order for the strip_insignificant_zeros option to work, though, otherwise the underlying number_with_precision method never gets called.
If you want to store as a float, you can use the number_to_currency(value) method in yours views for printing something that looks like $.
Correct me if I'm wrong (as I've rarely dealt with currency) but I think the conventional wisdom is to store dollar values as integers. That way you won't have to deal with funky float math.
So, convert it to three decimal fraction digits and then remove the final one if and only if it's a zero.
s.sub(/0$/, '')