如何将字符串解析为其数据类型?

时间:2015-11-16 12:11:55

标签: ruby parsing

我想按如下方式解析字符串:

"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

这可以满足需要,但它看起来很糟糕且效率低下。最好的方法是什么?

4 个答案:

答案 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