我有一个用户输入的字符串,我将其变成一个数组,然后遍历该数组并删除非数字值。
看起来我的正则表达式匹配工作了一半时间,并且我的to_f从未将数组值设置为浮点数。
假设我输入:“ 1 2 3b c3 4,5t”
puts "Enter Minutes"
STDOUT.flush
freq = gets.chomp
freq = freq.split(/\W/) #this creates the array, splitting at non-word chars
p freq #outputs: ["1", "2", "3b", "c3", "4", "", "5t"]
freq.each do |minutes|
if ( minutes == "" or /\D/.match(minutes) ) then freq.delete(minutes) else minutes.to_f end
end
p freq #outputs: ["1", "2", "c3", "4", "5t"]
我想要的结果是:[1、2、4] #note它们是数字而不是字符
答案 0 :(得分:5)
问题是您仅在then
条件下而不是在else条件下才对频率进行突变。
有许多可以为您突变的方法,它们通常以!
结尾:
freq = ["1", "2", "3b", "c3", "4", "", "5t"]
=> ["1", "2", "3b", "c3", "4", "", "5t"]
freq.reject! { |minutes| minutes.match(/\D/) || minutes == "" }.map! { |minutes| minutes.to_f }
=> [1.0, 2.0, 4.0]
答案 1 :(得分:4)
arr = ["1", "2", "3b", "c3", "4", "", "5t"]
有两种方法可以解决此问题。一种是执行两个步骤:删除所有不是非负整数表示形式的元素,然后将这些整数转换为浮点数,这需要对两个数组中的每个数组进行一次遍历。另一种方法是构建一个浮点数组,一次通过arr
。可以按照以下步骤进行。
arr.each_with_object([]) { |s,a| a << s.to_f if s.match?(/\A\d+\z/) }
#=> [1.0, 2.0, 4.0]
正则表达式为:“匹配字符串的开头(锚点\A
),然后是一个或多个数字,然后是字符串的结尾(锚点\z
)。与不匹配空字符串或非数字字符相同,因此我们可以这样写:
arr.each_with_object([]) { |s,a| a << s.to_f unless s.empty? or s.match?(/\D/) }
#=> [1.0, 2.0, 4.0]
在这两者之间没有太多选择,但是有时后一种方法更易于实现。
我不太喜欢(但值得了解)的另一种方法是使用方法Kernel#Float后跟Array#compact:
arr = ["1", "-2", "3b", "c3", "4.23", "", "5t", "-1.2e3"]
arr.map { |s| Float(s) rescue nil }.compact
#=> [1.0, -2.0, 4.23, -1200.0]
如所见,这会将arr
的表示整数或浮点数(不仅是非负整数)的元素转换为浮点数(可能需要也可能不需要)。
Float(s)
无法转换为浮点数,则 ArgumentError
引发s
。例如:
Float("3b")
#=> ArgumentError (invalid value for Float(): "3b")
发生这种情况时,我在内联救援条款中捕获了异常,返回了nil
。
一些红宝石不喜欢嵌入式救援条款,因为它们可以掩盖其他错误。只能通过拯救ArgumentErrors
来解决该问题:
arr.map do |s|
begin
Float(s)
rescue ArgumentError
nil
end
end.compact
#=> [1.0, -2.0, 4.23, -1200.0]