比gsub更有效的方式两次

时间:2016-10-17 18:34:09

标签: ruby-on-rails ruby regex

我有一个字符串数组:

orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]

我这样做是为了删除前导“#”并尾随“.1”

orders.each do |numbers|
  puts numbers.gsub!("#", "").gsub!(/\.[0-9]/, "")
end
# returns 1174, 1176 etc..

尾随的“.1”可以是任何数字到9 ..是否有更好/更快的方法来做到这一点?

7 个答案:

答案 0 :(得分:4)

一种方法:

orders.map { |s| s.sub('#','').to_i }
#=> [1174, 1176, 1177, 1178, 1180] 
如果你想要字符串,请在块中添加to_s

如果OP希望数字四舍五入。例如#1174.8返回1175等。然后这应该可以解决问题:

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"]

答案 1 :(得分:3)

我使用:

orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]
orders.map{ |n| n[/\d+/] } # => ["1174", "1176", "1177", "1178", "1180"]

/\d+/将返回找到的第一组数字,这意味着'#'.n将自动被忽略。

这是一个基准:

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%

答案 2 :(得分:2)

cleaned_orders = orders.map { |numbers| numbers.gsub(/(^#|\.\d$)/, '') }

cleaned_orders现在包含:['1174', '1176', '1177', '1178', '1180']

(^#|\.\d$)匹配#,如果它位于字符串的开头或单个句点,后跟字符串末尾的单个数字。

答案 3 :(得分:1)

看起来所有数字都有四位数。如果确实如此,您可能想尝试这个:

orders = ["#1174.2", "#1176.3", "#1177.2", "#1178.1", "#1180.1"]
orders.map { |n| n[1..-3] }
#=> ["1174","1176","1177","1178","1180"] 

这显然只有在所有数字具有相同的格式和长度时才有效,但它比使用正则表达式更快。<​​/ p>

答案 4 :(得分:1)

orders.map { |s| s[1..-1].to_i.to_s }
  #=> ["1174", "1176", "1177", "1178", "1180"]

如果需要整数数组而不是字符串数组,请删除.to_s

答案 5 :(得分:0)

尝试这样的事情

orders.map { |item| item.gsub(/#(\d+)(\.\d)?/, '\1') }
 => ["1174", "1176", "1177", "1178", "1180"] 

即使某些元素没有某个点,也可以使用。

答案 6 :(得分:-2)

使用此

orders.join.gsub(/\.[0-9]#/, "#").gsub(/\.[0-9]/, "").split("#") - [""]

返回

=> ["1174", "1176", "1177", "1178", "1180"]

<强>出资

此方法需要5个步骤。这与数组中有多少元素无关。

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"]