Как проанализировать число из строки, которая может иметь ведущий ноль?
Вопрос
В Ruby я анализирую дату в следующем формате:24092008.Я хочу преобразовать каждый раздел (год, месяц, дату) в число.
Я разделил их с помощью регулярного выражения, которое создает три строки, которые я передаю в конструктор Integer.
date =~ /^([\d]{2})([\d]{2})([\d]{4})/
year = Integer($3)
month = Integer($2)
day = Integer($1)
Когда он достигает линии месяца, происходит сбой следующим образом:
`Integer': invalid value for Integer: "09" (ArgumentError)
Мне потребовалось некоторое время, чтобы понять, что он интерпретирует начальный ноль как восьмеричный, а 09 не является допустимым восьмеричным числом (он отлично работает с «07»).
Есть ли элегантное решение этой проблемы или мне следует просто проверить числа меньше 10 и сначала удалить ноль?
Спасибо.
Решение
Я не знаком с регулярными выражениями, поэтому простите меня, если этот ответ не соответствует действительности.Я предполагал, что $3, $2 и $1 — это строки.Вот что я сделал в IRB, чтобы воспроизвести проблему:
irb(main):003:0> Integer("04")
=> 4
irb(main):004:0> Integer("09")
ArgumentError: invalid value for Integer: "09"
from (irb):4:in `Integer'
from (irb):4
from :0
Но похоже, что у .to_i таких проблем нет:
irb(main):005:0> "04".to_i
=> 4
irb(main):006:0> "09".to_i
=> 9
Другие советы
Укажите основание 10
Явно сообщите Ruby, что вы хотите интерпретировать строку как число по основанию 10.
Integer("09", 10) # => 9
Это лучше чем .to_i
если хочешь быть строгим.
"123abc".to_i # => 123
Integer("123abc", 10) # => ArgumentError
Как я это понял
В irb
, method(:Integer)
возвращает #<Method: Object(Kernel)#Integer>
.Это сказало мне, что Kernel
владеет этим методом, и я поискал документацию по Kernel. Сигнатура метода показывает, что он принимает базу в качестве второго аргумента.
Возможно (0([\d])|([1-9][\d]))
на месте ([\d]{2})
Возможно, вам придется использовать 2, 4 и 5 долларов вместо 1, 2 и 3 долларов.
Или, если ваше регулярное выражение поддерживает (?:...)
затем используйте (?:0([\d])|([1-9][\d]))
Поскольку Ruby берет регулярное выражение из Perl, последняя версия должна работать.