Проверка, является ли переменная целым числом


137

Есть ли в Rails 3 или Ruby встроенный способ проверки, является ли переменная целым числом?

Например,

1.is_an_int #=> true
"dadadad@asdasd.net".is_an_int #=> false?


1
Вместо того, чтобы заботиться о том, является ли переменная целым числом, вы должны проверить, отвечает ли переменная на to_i. Это часть «утиной печати» Ruby: если она может действовать как целое число, относитесь к нему как к единице.
Железный Человек

4
@ Железный Человек: Не совсем. "hello" .to_i возвращает 0, что может не соответствовать вашим ожиданиям.
EinLama 04

1
@AnApprentice Для вашей информации, kind_of?это псевдоним is_a?.
Джейкоб Релкин

3
@JacobRelkin is_a?немного отличается; он спрашивает, принадлежит ли объект экземпляру определенного класса; kind_of?спрашивает, является ли это экземпляром или дочерним элементом определенного класса. fido.is_a? Dogправда; fido.kind_of? Animalверно, например.
Том Харрисон

Ответы:


278

Вы можете использовать is_a?метод

>> 1.is_a? Integer
=> true
>> "dadadad@asdasd.net".is_a? Integer
=> false
>> nil.is_a? Integer
=> false

2
Это очень круто. это работает для проверки адресов электронной почты?
AnApprentice

65
@AnApprentice С каких это пор проверка адресов электронной почты была частью вопроса?
Джейкоб Релкин

4
это не сработает, если число будет заключено в строку типа «11111111»
Ricbermo

посмотрите ниже. Integer(obj) rescue false Это не сработает для "1", если вы хотите проверить, конвертируется ли он
mc.

4
@Ricbermo «1111111» - это строка. Строка, которая может быть преобразована в Integer.
Sqeaky

50

Если вы хотите знать, является ли объект объектом Integer или чем-то, что можно значимо преобразовать в целое число (НЕ включая такие вещи, как "hello", которые to_iбудут преобразованы в 0):

result = Integer(obj) rescue false

2
Может я просто новичок, но эта настройка мне бы помогла. result = Целое число (obj) rescue false.
Джон Карри

@JohnCurry, не стесняйтесь редактировать ответ, если можете его улучшить. Вот как работает ТАК.
Alex D

2
Я сделал, это было отклонено. «Это изменение отличается от первоначального замысла сообщения» Но несмотря на это, спасибо за ваш ответ, оно помогло мне решить мою проблему!
Джон Карри

7
Целое число ('08 ') завершится ошибкой, поскольку строка интерпретируется как восьмеричная, целое число ('08', 10) работает нормально. Так, на всякий случай.
Чон Бор Ли

1
Не уверен, что Integer(2.5) => 2это всегда значимое преобразование.
mkataja

29

Используйте регулярное выражение в строке:

def is_numeric?(obj) 
   obj.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end

Если вы хотите проверить, имеет ли переменная определенный тип, вы можете просто использовать kind_of?:

1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545"  #true
is_numeric? "2aa"  #false

Это именно то, что я искал is_numeric?
workdreamer

Думаю, это близко, но не совсем правильно. Например, для ".34" он не сработает. Проблема, я думаю, что в \d+?том ?специфицирует нежадное матч, в то время как вам , вероятно , хочет дополнительный матч. Изменение \d+?на \d*может исправить это, но я бы хотел провести его через набор тестов, чтобы убедиться. Это также не будет соответствовать шестнадцатеричной или экспоненциальной нотации, но я уверен, что это нормально для определенных случаев использования.
Джефф

1
Почему бы не просто использовать это регулярное выражение: \A\d+\z?
НАРКОЗ 03

1
Сравните с Integer(obj) rescue falseкодом из @ alex-d ниже; regexp трудно читать, и его назначение непонятно. Оба работают, я пришел к этому вопросу в попытке исправить плохо сконструированное регулярное выражение, которое не всегда работало :-)
Том Харрисон

17

Если вы не уверены в типе переменной (это может быть строка числовых символов), скажите, что это был номер кредитной карты, переданный в params, поэтому изначально это будет строка, но вы хотите убедиться, что это не так. Если в нем нет буквенных символов, я бы использовал этот метод:

    def is_number?(obj)
        obj.to_s == obj.to_i.to_s
    end

    is_number? "123fh" # false
    is_number? "12345" # true

@Benny указывает на недосмотр этого метода, имейте это в виду:

is_number? "01" # false. oops!

спасибо, ты спас мне день. Для тех, кому нужно проверить, плавает он или нет, можно напрямую изменить его obj.to_s == obj.to_f.to_sтак, как в моем случае.
ksugiarto

Эдмунд, это умно! 🙌
siwalikm

Замечательно, я предпочитаю это Integer ('123fh') и исключение спасения.
zw963

5

Там var.is_a? Class(в вашем случае :) var.is_a? Integer; это могло бы соответствовать всем требованиям. Или там Integer(var), где он выдаст исключение, если не сможет его проанализировать.


5

Вы можете использовать тройное равенство.

if Integer === 21 
    puts "21 is Integer"
end

3

Более «утиный» способ - использовать respond_to?этот способ также можно использовать классы «целочисленные» или «строковые».

if(s.respond_to?(:match) && s.match(".com")){
  puts "It's a .com"
else
  puts "It's not"
end

2

Если вам не нужно преобразовывать нулевые значения, я считаю методы to_iи to_fчрезвычайно полезными, поскольку они преобразуют строку либо в нулевое значение (если не конвертируемое или нулевое), либо в фактическое Integerили Floatзначение.

"0014.56".to_i # => 14
"0014.56".to_f # => 14.56
"0.0".to_f # => 0.0
"not_an_int".to_f # 0
"not_a_float".to_f # 0.0

"0014.56".to_f ? "I'm a float" : "I'm not a float or the 0.0 float" 
# => I'm a float
"not a float" ? "I'm a float" : "I'm not a float or the 0.0 float" 
# => "I'm not a float or the 0.0 float"

EDIT2: будьте осторожны, 0целочисленное значение не является ложным, это правда ( !!0 #=> true) (спасибо @prettycoder)

РЕДАКТИРОВАТЬ

Ах, только что узнал о темных случаях ... кажется, что это происходит только в том случае, если номер находится на первой позиции, хотя

"12blah".to_i => 12

0 правда в рубине!
prettycoder

1
@prettycoder, спасибо за внимание, я сразу исправлю это в ответе
Сирил Дюшон-Дорис

1

Чтобы извлечь выгоду из ответа Alex D , используя уточнения :

module CoreExtensions
  module Integerable
    refine String do
      def integer?
        Integer(self)
      rescue ArgumentError
        false
      else
        true
      end
    end
  end
end

Позже в вашем классе:

require 'core_ext/string/integerable'

class MyClass
  using CoreExtensions::Integerable

  def method
    'my_string'.integer?
  end
end

0

У меня была аналогичная проблема, прежде чем я пытался определить, является ли что-то строкой или каким-либо числом. Я пробовал использовать регулярное выражение, но это ненадежно для моего варианта использования. Вместо этого вы можете проверить класс переменной, чтобы узнать, является ли она потомком класса Numeric.

if column.class < Numeric
  number_to_currency(column)
else
  column.html_safe
end

В этой ситуации вы также можете заменить любой из числовых потомков: BigDecimal, Date :: Infinity, Integer, Fixnum, Float, Bignum, Rational, Complex


-1

Вероятно, вы ищете что-то вроде этого:

Принять "2.0 или 2.0 как INT, но отклонить 2.1 и 2.1"

число = 2,0

если num.is_a? String num = Float (num) спасает ложный конец

new_num = Целое число (число) спасение ложь

ставит число

помещает new_num

помещает num == new_num

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.