1

重複の可能性:
RubyonRailsで文字列が数値かどうかをテストします

現在、私はこの(ひどい)コードを持っています:

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

4 に答える 4

2

something.is_a?(Numeric)行く方法です。to_i後者の例を参照すると、入力を呼び出す必要はありません。

something.is_a?(Numeric)文字列が数字であるかどうかを確認しようとしている場合は機能しないことに注意してください...

于 2012-10-31T00:25:55.543 に答える
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
于 2012-10-31T00:48:21.327 に答える
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

(ただし、これを行うにはもっと自然な方法があるかもしれません。)

于 2012-10-30T23:47:46.427 に答える
0

いつでも単純な正規表現を使用できます。

def is_num(num_given)
  num_given =~ /\d+(\.\d+)?/
end
于 2012-10-30T23:43:29.873 に答える