Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strictly convert string to integer (or nil)

For web programming, numbers come in as strings. but to_i will convert "5abc" to 5 and "abc" to 0, both wrong answers. To catch these, I wrote:

def number_or_nil( s )   number = s.to_i   number = nil if (number.to_s != s)   return number end 

Is there a neater, more Ruby-natural way of accomplishing this conversion and detecting that the string wasn't intended as a number?

like image 664
Alistair Cockburn Avatar asked Jul 27 '14 11:07

Alistair Cockburn


People also ask

Can you convert string to integer?

In Java, we can use Integer.valueOf() and Integer.parseInt() to convert a string to an integer.

Can you convert string to int or float?

Strings can be converted to numbers by using the int() and float() methods.

Which function converts a string to integer numbers?

The atoi() function converts a character string to an integer value. The input string is a sequence of characters that can be interpreted as a numeric value of the specified return type. The function stops reading the input string at the first character that it cannot recognize as part of a number.

Why do we convert string to integer?

It is generally used if we have to perform mathematical operations on the string which contains a number. Whenever we receive data from TextField or TextArea, entered data is received as a string. If entered data is in number format, we need to convert the string to an int. To do so, we use Integer.parseInt() method.


2 Answers

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.

like image 197
Jim Gay Avatar answered Sep 28 '22 03:09

Jim Gay


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 

Note that Integer also leaves you the control of the base, something that to_i does not support:

> '0xf'.to_i => 0 > Integer('0xf') => 15 > Integer('10', 8) => 8 

When the base is specified, the radix-prefix (0x... etc.) must be consistent (if present):

> Integer('0xf', 10) => ArgumentError(invalid value for Integer(): "0xf") > Integer('0xf', 16) => 15 > Integer('f', 16) => 15 
like image 24
akim Avatar answered Sep 28 '22 01:09

akim