Ruby встроили эту функциональность:
Integer('1001') # => 1001
Integer('1001 nights')
# ArgumentError: invalid value for Integer: "1001 nights"
, Как отмечено в ответе Joseph Pecoraro , Вы могли бы хотеть наблюдать за строками, которые являются допустимыми недесятичными числами, такими как те, которые запускаются с 0x
для шестнадцатеричного числа и 0b
для двоичного файла и потенциально более хитрых чисел, запускающихся с нуля, который будет проанализирован как восьмеричный.
Ruby 1.9.2 добавил дополнительный второй аргумент в пользу основания, таким образом, выше проблемы может избежаться:
Integer('23') # => 23
Integer('0x23') # => 35
Integer('023') # => 19
Integer('0x23', 10)
# => #<ArgumentError: invalid value for Integer: "0x23">
Integer('023', 10) # => 23
Это могло бы работать:
i.to_i if i.match(/^\d+$/)
Также знайте о влиянии, которое текущее принятое решение может иметь при парсинге шестнадцатеричного числа, восьмеричных, и двоичных чисел:
>> Integer('0x15')
# => 21
>> Integer('0b10')
# => 2
>> Integer('077')
# => 63
В числах Ruby, которые запускаются с 0x
или 0X
, шестнадцатеричное число, 0b
или 0B
являются двоичными, и всего 0
являются восьмеричными. Если это не желаемое поведение, можно хотеть объединить это с некоторыми из других решений, которые проверяют, соответствует ли строка шаблону сначала. Как эти /\d+/
регулярные выражения, и т.д.
Я должен был иметь дело с этим в своем последнем проекте, и моя реализация была подобна, но немного отличалась:
class NotAnIntError < StandardError
end
class String
def is_int?
self =~ /^-?[0-9]+$/
end
def safe_to_i
return self.to_i if is_int?
raise NotAnIntError, "The string '#{self}' is not a valid integer.", caller
end
end
class Integer
def safe_to_i
return self
end
end
class StringExtensions < Test::Unit::TestCase
def test_is_int
assert "98234".is_int?
assert "-2342".is_int?
assert "02342".is_int?
assert !"+342".is_int?
assert !"3-42".is_int?
assert !"342.234".is_int?
assert !"a342".is_int?
assert !"342a".is_int?
end
def test_safe_to_i
assert 234234 == 234234.safe_to_i
assert 237 == "237".safe_to_i
begin
"a word".safe_to_i
fail 'safe_to_i did not raise the expected error.'
rescue NotAnIntError
# this is what we expect..
end
end
end
someString = "asdfasd123"
number = someString.to_i
if someString != number.to_s
puts "oops, this isn't a number"
end
, Вероятно, не самый чистый способ сделать это, но должен работать.
Ре: ответ Chris
Ваша реализация позволяют нам вещи как "1a" или "b2" через. Как насчет этого вместо этого:
def safeParse2(strToParse)
if strToParse =~ /\A\d+\Z/
strToParse.to_i
else
raise Exception
end
end
["100", "1a", "b2", "t"].each do |number|
begin
puts safeParse2(number)
rescue Exception
puts "#{number} is invalid"
end
end
Это производит:
100
1a is invalid
b2 is invalid
t is invalid
Еще одно неожиданное поведение с принятым решением (с 1.8, 1.9 в порядке):
>> Integer(:foobar)
=> 26017
>> Integer(:yikes)
=> 26025
поэтому, если вы не уверены, что передается, убедитесь, что вы добавили .to_s
.