Реализация Ruby is_numeric? для строк, нужны лучшие альтернативы
Я хотел проверить "численность" строки (ее не атрибут в модели с активной записью). Мне просто нужно, чтобы она была действительной базой 10, положительной целой строкой. Я делаю это:
class String
def numeric?
# Check if every character is a digit
!!self.match(/\A[0-9]+\Z/)
end
end
class String
def numeric?
# Check is there is *any* non-numeric character
!self.match(/[^0-9]/)
end
end
Какая из них является более правдоподобной альтернативой? ИЛИ, есть ли другая лучшая реализация?
Ответы
Ответ 1
Пожалуйста, используйте \A
и \Z
, а не ^
и $
, чтобы соответствовать всей строке, а не только одной строке строки. Если вы хотите избежать совпадения строки с конечной новой строкой, используйте '\ z' в конце. Дополнительные сведения см. В Учебное пособие по привязкам.
Например, /^[0-9]+$/
успешно соответствует следующему:
foo
1234
bar
но /\A[0-9]+\Z/
не работает.
Ответ 2
Первый выглядит для меня здоровым.
Я бы назвал метод numeric?
. Я не большой поклонник методов is_foo?
. Они имеют смысл в языках, которые не имеют вопросительных знаков в именах методов (is_foo
, isFoo
), но с вопросительным знаком is
чувствует себя излишним.
Ответ 3
Я не уверен на 100%, но Rails, похоже, использует /\A[+-]?\d+\Z/
для целых чисел.
Нажмите здесь, чтобы показать источник validates_numericality_of
здесь
Ответ 4
Я бы предложил другой способ сделать это. Кроме того, поскольку вы задали "положительное" целое число, я сделал два отдельных метода для положительного целого и неотрицательного целого числа.
class String
def numeric?
!self.match(/[^0-9]/)
end
def positive_integer?
self.to_i > 0
end
def nonnegative_integer?
self.to_i > 0 or self == '0'
end
end
Вот эталонный код:
require 'benchmark'
include Benchmark
bmbm(100) do |x|
x.report('numeric?') do
"some invalid string".numeric?
end
x.report('positive_integer?') do
"some invalid string".positive_integer?
end
x.report('nonnegative_integer?') do
"some invalid string".nonnegative_integer?
end
end
Результат:
numeric?
0.000000 0.000000 0.000000 ( 0.000045)
positive_integer?
0.000000 0.000000 0.000000 ( 0.000012)
nonnegative_integer?
0.000000 0.000000 0.000000 ( 0.000015)
Кажется, что positive_integer?
и nonnegative_integer?
быстрее в этом микро-контроле.
Наконец, в качестве побочной заметки вы можете определить метод integer?
следующим образом:
class String
def integer?
self.to_i.to_s == self
end
end
Ответ 5
Второй будет быстрее завершен в случае нечисловой строки, поскольку он отклонит первый плохой символ.
Также проверьте метод String # to_i - он, возможно, делает то, что вы хотите:
http://www.ruby-doc.org/core/classes/String.html#M000787
Ответ 6
Я не знаю, скоро ли это, но мне нравится:
class String
def numeric?
true if Integer(object) rescue false
end
end
Также обрабатывает отрицательные числа. И если вы когда-нибудь захотите поддерживать плавания в будущем, просто используйте Float()
Ответ 7
В соответствии с простым эталоном второй подход выполняется быстрее, хотя я не являюсь экспертным контрольным маркером, поэтому это может оказаться недействительным.
http://pastie.org/586777
Логика Залуса правильная. Это нужно только один раз проверить для недействительной строки.
Ответ 8
Примечание
n = '1234'
n.to_i.to_s == n
=> true
n2 = '1.3'
n.to_i.to_s == n2
=> false
работает с целыми положительными и отрицательными целыми числами, но не с восьмеричными представлениями, поплавками и т.д. Может не выполнять лучших (непроверенных), но не тратить время на то, чтобы избежать преждевременных оптимизаций.