我想按如下方式解析字符串:
"1.0" # => 1.0 (Float)
"1" # => 1 (FixNum)
"hello" # => "hello" (String)
"true" # => true (TrueClass)
"false" # => false (FalseClass)
我有以下代码:
def parse_value(val)
raise ArgumentError, "value must be a string" unless val.is_a? String
if val.to_i.to_s == val
val.to_i
elsif val.to_f.to_s == val
val.to_f
elsif val == 'true'
true
elsif val == 'false'
false
else
val
end
end
这可以满足需要,但它看起来很糟糕且效率低下。最好的方法是什么?
答案 0 :(得分:2)
如果不使用eval
,你就无法获得更简洁/优雅的代码,我担心。这是使用case/when
的变体,但它是同一头猪的口红。
def parse_value(val)
raise ArgumentError, "value must be a string" unless val.is_a? String
case val
when /\A\d+\z/
val.to_i
when /\A\d+(\.\d+)?\z/
val.to_f
when 'true'
true
when 'false'
false
else
val
end
end
答案 1 :(得分:1)
def parse_value(val)
raise ArgumentError, "value must be a string" unless val.is_a? String
case val
when /\A\d+\z/ then val.to_i
when /\A\d+(\.\d+)?\z/ then val.to_f
when 'true' then true
when 'false' then false
else val
end
end
我把它写成了Sergios答案的更简洁版本。 我想反馈一下这是否会违反Ruby风格指南。
答案 2 :(得分:0)
您可以将eval
与正则表达式一起使用:
def parse_string(val)
raise ArgumentError, "value must be a string" unless val.is_a? String
val =~ /\A(\d+(\.\d+)?|true|false)\z/ ? eval(val) : val
end
parse_string '1.0' #=> 1.0
parse_string '1' #=> 1
parse_string 'hello' #=> "hello"
parse_string 'true' #=> true
parse_string 'false' #=> false
答案 3 :(得分:0)
def convert(s)
i = Integer(s) rescue nil
return i if i
f = Float(s) rescue nil
return f if f
return true if s == "true"
return false if s == "false"
s
end
arr = %w| 1 1.0 true false hello |
#=> ["1", "1.0", "true", "false", "hello"]
arr.each { |s| e = convert(s); puts "#{e.class}: #{e}" }
# Fixnum: 1
# Float: 1.0
# TrueClass: true
# FalseClass: false
# String: hello