确定变量是否是Ruby中的数字的最佳方法是什么?

时间:2012-10-30 23:36:56

标签: ruby ruby-on-rails-3

  

可能重复:
  Test if string is a number in Ruby on Rails

目前我有这个(糟糕的)代码:

def is_num(num_given)
  begin
    num_given.to_i
    worked = true
  rescue
    worked = false
  ensure
    return worked
  end
end

我对此进行了重构:

def is_num(num_given)
  num_given.to_i.is_a?(Numeric) rescue false
end

这对我来说仍然感觉不对,有更好的方法吗?

这两个实现都适合我的目的,我只是寻找一些代码的兴奋。

4 个答案:

答案 0 :(得分:2)

something.is_a?(Numeric)是要走的路。请参阅后一个示例,无需在输入上调用to_i

请注意,如果您正在查看字符串是否为数字,则something.is_a?(Numeric)将无效...

答案 1 :(得分:2)

这是另一种解决方案。它不像Ruby那样,但这是故意的(例如,while在这种情况下比str.chars.each更快。)

# is a character between 0 and 9? (based on C's isdigit())
def digit?(c)
  o = c.ord
  o >= 48 && o <= 57 # '0'.ord, '9'.ord
end

# is a string numeric (i.e., represented as an integer or decimal)?
def numeric?(str)
  str = str.to_s unless str.is_a?(String)
  l = str.length
  i = 0

  while i < l
    c = str[i]
    if c == '.' || c == '-'
      i += 1
      next
    end

    return false if !digit?(c)

    i += 1
  end

  true
end

以下是单元测试。如果我错过了一个案子,请告诉我。对于其他回答者,只需将subject块更改为您的功能。

if $0 == __FILE__
  require 'minitest/autorun'
  describe :digit? do
    %w(- + : ? ! / \ ! @ $ ^ & *).each do |c|
      it "flunks #{c}" do
        digit?(c).must_equal false
      end
    end

    %w(0 1 2 3 4 5 6 7 8 9).each do |c|
      it "passes #{c}" do
        digit?(c).must_equal true
      end
    end
  end

  describe :numeric? do
    subject { :numeric? }
    %w(0 1 9 10 18 123.4567 -1234).each do |str|
      it "passes #{str}" do
        method(subject).call(str).must_equal true
      end
    end

    %w(-asdf 123.zzz blah).each do |str|
      it "flunks #{str}" do
        method(subject).call(str).must_equal false
      end
    end

    [-1.03, 123, 200_000].each do |num|
      it "passes #{num}" do
        method(subject).call(num).must_equal true
      end
    end
  end
end

答案 2 :(得分:1)

您列出的功能不起作用:

is_num("a") #=> true

问题是它们不会因无效输入而引发错误。你想要的是Integer,这将引发一个你可以解决的错误:

def is_num(num_given)
  !!Integer(num_given) rescue false
end

这有效:

irb(main):025:0> is_num("a")
=> false
irb(main):026:0> is_num(5)
=> true
irb(main):027:0> is_num((1..2))
=> false
irb(main):028:0> is_num("3")
=> true

(尽管如此,可能有一种更自然的方式。)

答案 3 :(得分:0)

您始终可以使用简单的正则表达式:

def is_num(num_given)
  num_given =~ /\d+(\.\d+)?/
end