ruby - 如何检查一个值是否是 Integer()、Float() 或 Rational() 的有效输入?

标签 ruby type-conversion

这大致基于“How to convert a String to Integer or Float”。

如果我想使用 Ruby 的内置转换机制将数字字符串输入转换为其“最合适的类型”,我可以这样做:

def convert(input)
  value = Integer(input) rescue nil
  value ||= Float(input) rescue nil
  value ||= Rational(input) rescue nil
  value
end

convert('1')     #=> 1
convert('1_000') #=> 1000
convert('0xff')  #=> 255
convert('0.5')   #=> 0.5
convert('1e2')   #=> 100.0
convert('1/2')   #=> (1/2)
convert('foo')   #=> nil

但是这种蛮力方法调用看起来很脏。有没有更优雅的方法来解决这个问题?我可以检查一个值是否是 Integer()Float()Rational() 的有效输入这样我就可以以更可控的方式调用这些方法?

最佳答案

使用尾随救援让我感到畏缩,因为它可以掩盖底层代码的问题,因为它捕获异常而不是 ArgumentError,这是失败的尝试转换会引发的。这不是那么简洁,但它会处理适当的异常:

def convert(input)
  value = begin
            Integer(input)
          rescue ArgumentError
            nil
          end

  value ||= begin
              Float(input)
            rescue ArgumentError
              nil
            end

  value ||= begin
              Rational(input)
            rescue ArgumentError
              nil
            end

  value
end

convert('1')     # => 1
convert('1_000') # => 1000
convert('0xff')  # => 255
convert('0.5')   # => 0.5
convert('1e2')   # => 100.0
convert('1/2')   # => (1/2)
convert('foo')   # => nil

稍微考虑一下之后,似乎可以将其归结为:

def convert(input)
  [:Integer, :Float, :Rational].each do |m| 
    begin
      return Kernel.method(m).call(input)
    rescue ArgumentError
    end
  end
  nil
end

convert('1')     # => 1
convert('1_000') # => 1000
convert('0xff')  # => 255
convert('0.5')   # => 0.5
convert('1e2')   # => 100.0
convert('1/2')   # => (1/2)
convert('foo')   # => nil

正如 Jörn 所指出的,以上例子并不是很好的例子。我使用 Kernel 获取 Integer()Float()Rational,因为那是定义它们的地方,但实际上对象是值得一看的地方,因为它继承自内核。

那是我知道有一种间接调用该方法的好方法的那些日子之一,但 call 一直在我脑海中萦绕,而不是 send正如斯蒂芬指出的那样。因此,这是一种更简洁的方法,从以下开始:

  return Object.send(m, input)

但是,这可以简化为:

 return send(m, input)

导致:

def convert(input)
  [:Integer, :Float, :Rational].each do |m| 
    begin
      return send(m, input)
    rescue ArgumentError
    end
  end
  nil
end

convert('1')     # => 1
convert('1_000') # => 1000
convert('0xff')  # => 255
convert('0.5')   # => 0.5
convert('1e2')   # => 100.0
convert('1/2')   # => (1/2)
convert('foo')   # => nil

关于ruby - 如何检查一个值是否是 Integer()、Float() 或 Rational() 的有效输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40722804/

相关文章:

java - 将 int 转换为 int 数组

javascript - PHP 字符串到整数的转换不适用于此代码

ruby - 使用自定义命名空间解析 Ruby 中的 ATOM

安卓房间 : Efficient way to transform json result into db object

ruby - 使用 Ruby 的 TCPSocket 类发送原始字节数组的最简单方法

ruby-on-rails - 对 Rails has_and_belongs_to_many 关联感到困惑

C++ 浮点到整数类型的转换

mysql - 从 latin_swedish_ci 检索内容并将其存储到 utf8_general_ci

ruby - Vagrant 显然没有正确合并 Vagrantfiles,Chef 配置丢失

ruby-on-rails - Rails、STI 和 'becomes' - f.object.errors 未显示在 View 中