Дается строковый объект вида:
twohundred = "200"
В чем разница между выполнением:
Integer(twohundred) #=> 200
и:
twohundred.to_i #=> 200
Есть ли разница? Рекомендуется ли использовать один из них в сочетании с другим?
Integer(num)
вызовет исключение ArgumentError
, если num не является допустимым целым числом (можно указать основание).
num.to_i
преобразует столько, сколько сможет.
Например:
"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
Из документации по Ruby для Integer()
:
Integer(arg,base=0) → integer ... Если arg - строка, если base опущен или равен нулю, то радикс индикаторы (0, 0b и 0x) выполняются. В любом случае, строки должны быть строго соответствовать числовому представлению. Такое поведение отличается от поведения String#to_i.
Другими словами, Integer("0x100") => 256
и "0x100".to_i => 0
.
Рассмотрим различия между использованием метода экземпляра String#to_i и метода модуля Kernel::Integer. Сначала, однако, встроим последующий в другой метод int1
:
def int1(str)
Integer(str) rescue nil
end
Таким образом, если str
не может быть интерпретировано как целое число, то Integer
вызовет исключение ArgumentError
, в результате чего встроенное спасение вернет nil
. Если Integer
не вызовет исключения, то int
вернет целочисленный эквивалент строки.
Чтобы завершить сравнение, добавим регулярное выражение, которое подтверждает, что содержимое строки представляет собой целое число, прежде чем использовать to_i
для преобразования.
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
Как и в случае с int1
, если str
не может быть интерпретирована как целое число, то int2
вернет nil
; в противном случае int
вернет целочисленный эквивалент строки.
Попробуем провести некоторые сравнения.
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 #=> 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 считывает цифры (возможно, перед которыми стоит знак минус) до тех пор, пока не прочитает символ пробела или не достигнет конца строки. Затем она просто преобразует эти цифры и возможный знак минус в Fixnum
, которое и возвращает. Конечно, to_i
имеет свое применение, но эти примеры показывают, что следует использовать int1
или int2
, если требуется вернуть nil
, если строка не содержит представления целого числа.