Reputation: 3258
I have an array of strings:
orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]
I am doing this to remove the leading "#" and trailing ".1"
orders.each do |numbers|
puts numbers.gsub!("#", "").gsub!(/\.[0-9]/, "")
end
# returns 1174, 1176 etc..
The trailing ".1" could be any number to 9.. is there a better/faster way to do this?
Upvotes: 0
Views: 547
Reputation: 9497
One way to do this:
orders.map { |s| s.sub('#','').to_i }
#=> [1174, 1176, 1177, 1178, 1180]
add to_s
in the block if you want strings.
In case the OP wants the numbers rounded. e.g. #1174.8
returns 1175
etc. Then this should do the trick:
orders = ["#1174.2", "#1176.5", "#1177.2", "#1178.7", "#1180.1"]
#=> ["#1174.2", "#1176.5", "#1177.2", "#1178.7", "#1180.1"]
orders.map { |s| s.sub('#','').to_f.round.to_s }
#=> ["1174", "1177", "1177", "1179", "1180"]
Upvotes: 4
Reputation: 106972
It looks like all the numbers have four digits. If that is always true you might want to try this:
orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]
orders.map { |n| n[1..-3] }
#=> ["1174","1176","1177","1178","1180"]
This obviously works only if all numbers have the same format and length, but it is way faster than using a regexp.
Upvotes: 1
Reputation: 110725
orders.map { |s| s[1..-1].to_i.to_s }
#=> ["1174", "1176", "1177", "1178", "1180"]
Remove .to_s
if you want an array of integers rather than an array of strings.
Upvotes: 1
Reputation: 160571
I'd use:
orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]
orders.map{ |n| n[/\d+/] } # => ["1174", "1176", "1177", "1178", "1180"]
/\d+/
will return the first group of digits found, which means that '#'
and .n
will be ignored automatically.
Here's a benchmark:
require 'fruity'
orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]
compare do
ttm { orders.map{ |n| n[/\d+/] } }
ursus { orders.map { |item| item.gsub(/#(\d+)(\.\d)?/, '\1') } }
dinesh { orders.join.gsub(/\.[0-9]#/, "#").gsub(/\.[0-9]/, "").split("#") - [""] }
sagarpandya82 { orders.map { |s| s.sub('#','').to_i.to_s } }
infused { orders.map { |numbers| numbers.gsub(/(^#|\.\d$)/, '') } }
end
# >> Running each test 1024 times. Test will take about 1 second.
# >> ttm is faster than sagarpandya82 by 60.00000000000001% ± 10.0%
# >> sagarpandya82 is faster than dinesh by 2.0x ± 0.1
# >> dinesh is faster than infused by 39.99999999999999% ± 10.0%
# >> infused is faster than ursus by 10.000000000000009% ± 10.0%
Upvotes: 3
Reputation: 3633
Use this
orders.join.gsub(/\.[0-9]#/, "#").gsub(/\.[0-9]/, "").split("#") - [""]
Returns
=> ["1174", "1176", "1177", "1178", "1180"]
BreakDown
This method takes 5 steps. This is irrespective of how much elements you have in array.
2.2.5 :019 > orders.join
=> "#1174.2#1176.3#1177.2#1178.1#1180.1"
2.2.5 :020 > orders.join.gsub(/\.[0-9]#/, "#")
=> "#1174#1176#1177#1178#1180.1"
2.2.5 :021 > orders.join.gsub(/\.[0-9]#/, "#").gsub(/\.[0-9]/, "")
=> "#1174#1176#1177#1178#1180"
2.2.5 :022 > orders.join.gsub(/\.[0-9]#/, "#").gsub(/\.[0-9]/, "").split("#")
=> ["", "1174", "1176", "1177", "1178", "1180"]
2.2.5 :023 > orders.join.gsub(/\.[0-9]#/, "#").gsub(/\.[0-9]/, "").split("#") - [""]
=> ["1174", "1176", "1177", "1178", "1180"]
Upvotes: -2
Reputation: 24337
cleaned_orders = orders.map { |numbers| numbers.gsub(/(^#|\.\d$)/, '') }
cleaned_orders
now contains: ['1174', '1176', '1177', '1178', '1180']
(^#|\.\d$)
matches # if it is at the beginning of the string or a single period followed by a single digit at the end of the string.
Upvotes: 2
Reputation: 30071
Try something like this
orders.map { |item| item.gsub(/#(\d+)(\.\d)?/, '\1') }
=> ["1174", "1176", "1177", "1178", "1180"]
This works even if some elements doesn't have a dot something end.
Upvotes: 0