Проверить, является ли строка в целом целым числом в кавычках, используя Ruby?
Мне нужна функция is_an_integer, где
"12".is_an_integer? returns true
"blah".is_an_integer? returns false
как я могу сделать это в рубине? я бы написал регулярное выражение, но я предполагаю, что есть помощник для этого, о котором я не знаю
20 ответов
Вы можете использовать регулярные выражения. Вот функция с предложениями @janm.
class String
def is_i?
!!(self =~ /\A[-+]?[0-9]+\z/)
end
end
Отредактированная версия согласно комментарию от @wich:
class String
def is_i?
/\A[-+]?\d+\z/ === self
end
end
Если вам нужно только проверить положительные числа
if !/\A\d+\z/.match(string_to_check)
#Is not a positive number
else
#Is all good ..continue
end
Ну вот простой способ:
class String
def is_integer?
self.to_i.to_s == self
end
end
>> "12".is_integer?
=> true
>> "blah".is_integer?
=> false
РЕДАКТИРОВАТЬ: Я не согласен с решениями, которые вызывают исключение для преобразования строки - исключения не поток управления, и вы могли бы также сделать это правильно. Тем не менее, мое решение выше не имеет дело с целыми числами не-10. Итак, вот как это сделать, не прибегая к исключениям:
class String
def integer?
[ # In descending order of likeliness:
/^[-+]?[1-9]([0-9]*)?$/, # decimal
/^0[0-7]+$/, # octal
/^0x[0-9A-Fa-f]+$/, # hexadecimal
/^0b[01]+$/ # binary
].each do |match_pattern|
return true if self =~ match_pattern
end
return false
end
end
Ты можешь использовать Integer(str)
и посмотрим, поднимется ли она:
def is_num?(str)
!!Integer(str, 10)
rescue ArgumentError, TypeError
false
end
Приложение: Следует отметить, что хотя это действительно вернет "01"
не для "09"
, просто потому что 09
не будет действительным целочисленным литералом.
Приложение к приложению: исправлено путем изменения Integer(str)
в Integer(str, 10)
согласно комментарию @jason-axelson.
Ruby 2.6.0 включает приведение к целому числу, не вызывая исключения, и возвращает nil
если произойдет сбой. И с тех пор nil
в основном ведет себя как false
в Ruby вы можете легко проверить целое число следующим образом:
if Integer(my_var, exception: false)
# do something if my_var can be cast to an integer
end
"12".match(/^(\d)+$/) # true
"1.2".match(/^(\d)+$/) # false
"dfs2".match(/^(\d)+$/) # false
"13422".match(/^(\d)+$/) # true
Вы можете сделать один вкладыш:
str = ...
int = Integer(str) rescue nil
if int
int.times {|i| p i}
end
или даже
int = Integer(str) rescue false
В зависимости от того, что вы пытаетесь сделать, вы также можете напрямую использовать начальный конечный блок с предложением восстановления:
begin
str = ...
i = Integer(str)
i.times do |j|
puts j
end
rescue ArgumentError
puts "Not an int, doing something else"
end
Лучший и простой способ использует Float
val = Float "234" rescue nil
Float "234" rescue nil #=> 234.0
Float "abc" rescue nil #=> nil
Float "234abc" rescue nil #=> nil
Float nil rescue nil #=> nil
Float "" rescue nil #=> nil
Integer
тоже хорошо но вернется 0
за Integer nil
class String
def integer?
Integer(self)
return true
rescue ArgumentError
return false
end
end
- Это не префикс с
is_
, Я считаю, что глупо на вопросительных знаках, мне нравится"04".integer?
намного лучше чем"foo".is_integer?
, - Он использует разумное решение от sepp2k, которое проходит для
"01"
и тому подобное. - Объектно-ориентированный, ура.
Я предпочитаю:
конфиг / Инициализаторы /string.rb
class String
def number?
Integer(self).is_a?(Integer)
rescue ArgumentError, TypeError
false
end
end
а потом:
[218] pry(main)> "123123123".number?
=> true
[220] pry(main)> "123 123 123".gsub(/ /, '').number?
=> true
[222] pry(main)> "123 123 123".number?
=> false
или проверьте номер телефона:
"+34 123 456 789 2".gsub(/ /, '').number?
Лично мне нравится подход исключения, хотя я сделал бы это немного более кратким.
class String
def integer?(str)
!!Integer(str) rescue false
end
end
Однако, как уже говорили другие, это не работает с октальными строками...
Гораздо проще может быть
/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
Может не подходить для всех случаев, но простой
"12".to_i => 12
"blah".to_i => 0
может также сделать для некоторых.
Так что, если это число, а не 0, оно вернет число. Если он возвращает 0, это либо слово, либо 0.
Решение:
# /initializers/string.rb
class String
IntegerRegex = /^(\d)+$/
def integer?
!!self.match(IntegerRegex)
end
end
# any_model_or_controller.rb
'12345'.integer? # true
'asd34'.integer? # false
Объяснение:
/^(\d)+$/
является регулярным выражением для поиска цифр в любой строке. Вы можете проверить свои выражения регулярных выражений и результаты на http://rubular.com/.- Мы сохраняем это в постоянной
IntegerRegex
чтобы избежать ненужного выделения памяти каждый раз, когда мы используем его в методе. integer?
вопросительный метод, который должен вернутьtrue
или жеfalse
,match
метод на строке, который соответствует вхождениям в соответствии с заданным выражением регулярного выражения в аргументе и возвращает совпадающие значения илиnil
,!!
преобразует результатmatch
метод в эквивалентный логический.- И объявление метода в существующих
String
класс - это патч обезьяны, который ничего не меняет в существующих функциях String, а просто добавляет другой метод с именемinteger?
на любом объекте String.
Хотя явного использования оператора равенства регистра следует избегать, Regexp#===
выглядит очень чисто здесь:
def integer?(str)
/\A[+-]?\d+\z/ === str
end
integer? "123" # true
integer? "-123" # true
integer? "+123" # true
integer? "a123" # false
integer? "123b" # false
integer? "1\n2" # false
Для более обобщенных случаев (включая числа с десятичной точкой) вы можете попробовать следующий метод:
def number?(obj)
obj = obj.to_s unless obj.is_a? String
/\A[+-]?\d+(\.[\d]+)?\z/.match(obj)
end
Вы можете проверить этот метод в сеансе irb:
(irb)
>> number?(7)
=> #<MatchData "7" 1:nil>
>> !!number?(7)
=> true
>> number?(-Math::PI)
=> #<MatchData "-3.141592653589793" 1:".141592653589793">
>> !!number?(-Math::PI)
=> true
>> number?('hello world')
=> nil
>> !!number?('hello world')
=> false
Для подробного объяснения регулярного выражения здесь, проверьте эту статью в блоге:)
Расширяя ответ @rado выше, можно также использовать троичное выражение для принудительного возврата истинных или ложных логических значений без использования двойных ударов. Конечно, версия с двойным логическим отрицанием является более краткой, но, вероятно, труднее читать для новичков (таких как я).
class String
def is_i?
self =~ /\A[-+]?[0-9]+\z/ ? true : false
end
end
Один лайнер в string.rb
def is_integer?; true if Integer(self) rescue false end
Мне нравится следующее:
def is_integer?(str)
str.to_i != 0 || str == '0' || str == '-0'
end
is_integer?('123')
=> true
is_integer?('sdf')
=> false
is_integer?('-123')
=> true
is_integer?('0')
=> true
is_integer?('-0')
=> true
Но осторожно:
is_integer?('123sdfsdf')
=> true
Я не уверен, было ли это когда задан этот вопрос, но... Для всех, кто наткнулся на этот пост, самый простой способ
var = "12"
var.is_a?(Integer) # returns false
var.is_a?(String) # returns true
var = 12
var.is_a?(Integer) # returns true
var.is_a?(String) # returns false
.это? будет работать с любым объектом!
Вы можете использовать is_a? метод. например, 1.is_a? Целое число вернет истину