Как проверить, является ли строка в целом целым числом в кавычках, используя Ruby

Мне нужна функция 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