Nobita
Nobita

Reputation: 23713

Difference between Integer(value) and value.to_i

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

Answers (3)

bta
bta

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

pjumble
pjumble

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

Cary Swoveland
Cary Swoveland

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

Related Questions