Reputation: 23713
Given a string object like this:
twohundred = "200"
What is the difference between doing:
Integer(twohundred) #=> 200
and:
twohundred.to_i #=> 200
Is there any difference? Is it recommended to use one among the other one?
Upvotes: 43
Views: 21927
Reputation: 45057
From the Ruby documentation for Integer()
:
Integer(arg,base=0) → integer ... If arg is a String, when base is omitted or equals to zero, radix indicators (0, 0b, and 0x) are honored. In any case, strings should be strictly conformed to numeric representation. This behavior is different from that of String#to_i.
In other words, Integer("0x100") => 256
and "0x100".to_i => 0
.
Another example: Integer("0010") => 8
and "0010".to_i => 10
.
Upvotes: 11
Reputation: 16960
Integer(num)
will throw an ArgumentError
exception if num isn't a valid integer (you can specify the base).
num.to_i
will convert as much as it can.
For example:
"2hi".to_i
#=> 2
Integer("2hi")
#=> throws ArgumentError
"hi".to_i
#=> 0
Integer("hi")
#=> throws ArgumentError
"2.0".to_i
#=> 2
Integer("2.0")
#=> throws ArgumentError
Upvotes: 64
Reputation: 110675
Let's examine differences between using the instance method String#to_i and the module method Kernel::Integer. First, however, let's embed the later in another method int1
:
def int1(str)
Integer(str) rescue nil
end
That way, if str
cannot be construed as an integer, Integer
will raise an ArgumentError
exception, causing the in-line rescue to return nil
. If Integer
does not raise an execption int
will return the integer equivalent of the string.
To round out the comparisons, let's also add a regular expression that confirms the contents of the string represents an integer before using to_i
to make the conversion.
R = /
(?<=\A|\s) # match beginning of string or whitespace character (positive lookbehind)
-? # optionally match a minus sign
\d+ # match one or more digits
(?=\s|\z) # match whitespace character or end of string (positive lookahead)
/x # free spacing regex definition mode
def int2(str)
str =~ R ? str.to_i : nil
end
As with int1
, if str
cannot be construed as an integer, int2
will return nil
; else, int
returns the integer equivalent of the string.
Let's try some comparisons.
str = '3'
str.to_i #=> 3
int1(str) #=> 3
int2(str) #=> 3
str = '-3'
str.to_i #=> -3
int1(str) #=> -3
int2(str) #=> -3
str = '3.0'
str.to_i #=> 3
int1(str) #=> nil
int2(str) #=> nil
str = '3.2'
str.to_i #=> 3
int1(str) #=> nil
int2(str) #=> nil
1e3 #=> 1000.0
str = '1e3'
str.to_i #=> 1
int1(str) #=> nil
int2(str) #=> nil
str = '-1e3'
str.to_i #=> -1
int1(str) #=> nil
int2(str) #=> nil
str = '- 1e3'
str.to_i #=> 0
int1(str) #=> nil
int2(str) #=> nil
str = '3a'
str.to_i #=> 3
int1(str) #=> nil
int2(str) #=> nil
str = '1-3a'
str.to_i #=> 1
int1(str) #=> nil
int2(str) #=> nil
str = 'b3'
str.to_i #=> 0
int1(str) #=> nil
int2(str) #=> nil
String#to_i reads digits (possibly preceded by a minus sign) until it reads a whitespace character or reaches the end of the string. It then merely converts those digits and possible minus sign to a Fixnum
, which it returns. to_i
certainly has its uses, but these examples show that you should use int1
or int2
if you wish to return nil
if the string does not contain the representation of an integer.
Upvotes: 3