Мне нужна функция is_an_integer
, где
-
"12".is_an_integer?
возвращает истину. -
"blah".is_an_integer?
возвращает ложь
Как я могу сделать это в Ruby? Я написал бы регулярное выражение, но я предполагаю, что есть помощник для этого, о котором я не знаю.
Ответ 1
Вы можете использовать регулярные выражения. Вот функция с предложениями @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
Ответ 2
Ну, вот простой способ:
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
Ответ 3
Вы можете использовать Integer(str)
и посмотреть, повысится ли он:
def is_num?(str)
!!Integer(str)
rescue ArgumentError, TypeError
false
end
Следует отметить, что хотя это возвращает true для "01"
, оно не для "09"
, просто потому, что 09
не будет действительным целочисленным литералом. Если это не то поведение, которое вам нужно, вы можете добавить 10
в качестве второго аргумента к Integer
, поэтому число всегда интерпретируется как основание 10.
Ответ 4
"12".match(/^(\d)+$/) # true
"1.2".match(/^(\d)+$/) # false
"dfs2".match(/^(\d)+$/) # false
"13422".match(/^(\d)+$/) # true
Ответ 5
Вы можете сделать один лайнер:
str = ...
int = Integer(str) rescue nil
if int
int.times {|i| p i}
end
или даже
int = Integer(str) rescue false
В зависимости от того, что вы пытаетесь сделать, вы также можете напрямую использовать блок начального конца с предложением rescue:
begin
str = ...
i = Integer(str)
i.times do |j|
puts j
end
rescue ArgumentError
puts "Not an int, doing something else"
end
Ответ 6
Ruby 2.6.0 разрешает приведение к целому числу, не вызывая исключения, и возвращает nil
если приведение не выполнено. А поскольку в Ruby nil
основном ведет себя как false
, вы можете легко проверить целое число следующим образом:
if Integer(my_var, exception: false)
# do something if my_var can be cast to an integer
end
Ответ 7
class String
def integer?
Integer(self)
return true
rescue ArgumentError
return false
end
end
- Это не префикс
is_
. Я нахожу это глупым в вопросительных методах, мне нравится "04".integer?
намного лучше, чем "foo".is_integer?
.
- Он использует разумное решение sepp2k, которое проходит для
"01"
и т.д.
- Объектно-ориентированный, yay.
Ответ 8
Самый простой и простой способ - использовать 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
Ответ 9
Я предпочитаю:
конфиг/Инициализаторы/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?
Ответ 10
Более простой способ может быть
/(\D+)/.match('1221').nil? #=> true
/(\D+)/.match('1a221').nil? #=> false
/(\D+)/.match('01221').nil? #=> true
Ответ 11
def isint(str)
return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
end
Ответ 12
Лично мне нравится подход исключения, хотя я бы сделал его немного более кратким:
class String
def integer?(str)
!!Integer(str) rescue false
end
end
Однако, как уже говорили другие, это не работает со строками Octal.
Ответ 13
В Ruby 2.4 есть соответствие Regexp#match?
: (с собой ?
)
def integer?(str)
/\A[+-]?\d+\z/.match? str
end
Для более старых версий Ruby существует 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
Ответ 14
Это может не подходить для всех случаев, просто используя:
"12".to_i => 12
"blah".to_i => 0
может также сделать для некоторых.
Если это число, а не 0, он вернет число. Если он возвращает 0, то это либо строка, либо 0.
Ответ 15
Вот мое решение:
# /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.
Ответ 16
Развернувшись на ответе @rado выше, вы также можете использовать тройную инструкцию для принудительного возврата истинных или ложных логических значений без использования двойных импульсов. Разумеется, версия с двойным логическим отрицанием является более кратким, но, вероятно, сложнее читать для новичков (например, я).
class String
def is_i?
self =~ /\A[-+]?[0-9]+\z/ ? true : false
end
end
Ответ 17
Для более обобщенных случаев (включая числа с десятичной точкой)
вы можете попробовать следующий метод:
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
Подробное объяснение используемого здесь регулярного выражения можно найти в этой статье в блоге:)
Ответ 18
Мне нравится следующее, прямо вперед:
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
Ответ 19
Один вкладыш в string.rb
def is_integer?; true if Integer(self) rescue false end
Ответ 20
Я не уверен, было ли это когда-то, когда задают этот вопрос, но для любого, кто натыкается на этот пост, самый простой способ:
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?
будет работать с любым объектом.
Ответ 21
вы можете использовать is_a? метод.
например. 1.is_a? Integer вернет true