Strictly convert string to integer (or nil)

后端 未结 3 836
醉酒成梦
醉酒成梦 2020-12-29 19:34

For web programming, numbers come in as strings. but to_i will convert \"5abc\" to 5 and \"abc\" to 0, both

相关标签:
3条回答
  • 2020-12-29 19:52

    Since at least Ruby 2.6, the kernel functions Integer, Float, etc. accept an exception keyword argument that does the job:

    > Integer('42', exception: false)
    => 42
    > Integer('x42', exception: false)
    => nil
    > Integer('x42')
    ArgumentError (invalid value for Integer(): "x42")
    > Integer('', exception: false)
    => nil
    > Integer('')
    ArgumentError (invalid value for Integer(): "")
    > Integer(nil, exception: false)
    => nil
    > Integer(' 42 ', exception: false)
    => 42
    > Integer(' 4 2 ', exception: false)
    => nil
    
    0 讨论(0)
  • 2020-12-29 19:53

    Use a simple regex to check str is an integer.

    def number_or_nil(str)
       str.to_i if str[/^-?\d+$/] and str.line.size == 1
    end
    
    0 讨论(0)
  • 2020-12-29 20:05

    Use Integer(string)

    It will raise an ArgumentError error if the string cannot convert to an integer.

    Integer('5abc') #=> ArgumentError: invalid value for Integer(): "5abc"
    Integer('5') #=> 5
    

    You'd still need your number_or_nil method if you want the behavior to be that nil is returned when a string cannot be converted.

    def number_or_nil(string)
      Integer(string || '')
    rescue ArgumentError
      nil
    end
    

    You should be careful to rescue from a particular exception. A bare rescue (such as "rescue nil") will rescue from any error which inherits from StandardError and may interfere with the execution of your program in ways you don't expect. Integer() will raise an ArgumentError, so specify that.

    If you'd rather not deal with exceptions and just prefer a shorter version of your number_or_nil you can take advantage of implicit return values and write it as:

    def number_or_nil(string)
      num = string.to_i
      num if num.to_s == string
    end
    
    number_or_nil '5' #=> 5
    number_or_nil '5abc' #=> nil
    

    This will work the way you expect.

    0 讨论(0)
提交回复
热议问题