Verificando se uma variável é um número inteiro

137

O Rails 3 ou Ruby tem uma maneira integrada de verificar se uma variável é um número inteiro?

Por exemplo,

1.is_an_int #=> true
"[email protected]".is_an_int #=> false?
Um aprendiz
fonte
possível duplicata do ruby 1.9.2 possui um is_a? função?
Andrew Grimm
1
Em vez de se importar se uma variável é um número inteiro, verifique se a variável responde to_i. Isso faz parte da "digitação de pato" de Ruby: se ele pode agir como um número inteiro, trate-o como um.
the Tin Man
4
@ The Tin Man: Não inteiramente. "olá" .to_i retorna 0, que pode não ser o que você espera.
EinLama
1
@AnApprentice Para sua informação, kind_of?é um apelido para is_a?.
Jacob Relkin
3
@JacobRelkin is_a?é um pouco diferente; pergunta se o objeto de uma instância de uma classe específica; kind_of?pergunta se é uma instância ou filho de uma classe específica. fido.is_a? Dogé verdade; fido.kind_of? Animalé verdade, por exemplo.
Tom Harrison

Respostas:

274

Você pode usar o is_a?método

>> 1.is_a? Integer
=> true
>> "[email protected]".is_a? Integer
=> false
>> nil.is_a? Integer
=> false
mportiz08
fonte
2
Isso é muito legal. funciona para validar endereços de email?
AnApprentice
65
@AnApprentice Desde quando a validação de endereços de e-mail faz parte da pergunta?
Jacob Relkin
4
isso não funcionará se o número
aparecer
veja abaixo Integer(obj) rescue false Isso não funcionará para "1" se você quiser verificar se ele converterá
mc.
4
@Ricbermo "1111111" é uma String. Uma String que passa a ser conversível em e Inteiro.
Sqeaky
50

Se você deseja saber se um objeto é um objeto Integer ou algo que pode ser convertido significativamente em um número inteiro (NÃO incluindo coisas como "hello", que to_iserá convertido em 0):

result = Integer(obj) rescue false
Alex D
fonte
2
Talvez eu seja apenas um noob, mas esse ajuste teria me ajudado. resultado = resgate inteiro (obj) false.
John Curry
@ JohnCurry, fique à vontade para editar a resposta, se puder melhorá-la. É assim que o SO funciona.
Alex D
2
Eu fiz, foi rejeitado. "Esta edição diverge da intenção original da postagem" Mas, independentemente disso, obrigado pela resposta, ela me ajudou a resolver meu problema!
John Curry
7
O número inteiro ('08 ') falhará devido à seqüência de caracteres ser interpretada como octal, o número inteiro ('08', 10) funciona bem. Apenas no caso de.
Jong Bor Lee
1
Não tenho certeza se Integer(2.5) => 2é sempre uma conversão significativa.
Mkataja
29

Use uma expressão regular em uma string:

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

Se você deseja verificar se uma variável é de determinado tipo, você pode simplesmente usar kind_of?:

1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545"  #true
is_numeric? "2aa"  #false
Jacob Relkin
fonte
Este é exatamente o que eu estava procurando o is_numeric?
Workdreamer)
Eu acho que isso está próximo, mas não exatamente correto. Por exemplo, falhará em ".34". O problema, penso eu, é que \d+?nos ?especifica um jogo não-gananciosos, enquanto você provavelmente quer uma correspondência opcional. Alterar \d+?para \d*pode corrigi-lo, mas eu gostaria de executá-lo através de um conjunto de testes para ter certeza. Isso também não corresponde à notação hexadecimal ou exponencial, mas tenho certeza de que isso é bom para certos casos de uso.
24412 Jeff
1
Por que não usar apenas este regexp \A\d+\z:?
NARKOZ
1
Compare com o Integer(obj) rescue falsecódigo de @ alex-d abaixo; O regexp é difícil de ler e não é claro em sua intenção. Ambos trabalham, eu vim a esta pergunta em uma tentativa de corrigir um regexp mal construídos que nem sempre estava trabalhando :-)
Tom Harrison
17

Se você não tiver certeza do tipo da variável (pode ser uma sequência de caracteres numéricos), diga que era um número de cartão de crédito passado para os parâmetros, portanto, originalmente seria uma sequência, mas você deseja garantir que não Se houver caracteres de letra, eu usaria este método:

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

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

@Benny destaca uma supervisão desse método, lembre-se disso:

is_number? "01" # false. oops!
bigpotato
fonte
obrigado, você salva meu dia. Para quem precisa verificar se flutua ou não, pode mudar diretamente para obj.to_s == obj.to_f.to_sexatamente como no meu caso.
ksugiarto
Edmund que é esperto! Si
siwalikm
Impressionante, eu prefiro isso do que Inteiro ('123fh') e exceção de resgate.
Zw963
6

Você pode usar o triplo igual.

if Integer === 21 
    puts "21 is Integer"
end
Tsoodol
fonte
5

Existe var.is_a? Class(no seu caso var.is_a? Integer:); isso pode se encaixar na conta. Ou há Integer(var), onde ele lançará uma exceção se não puder analisá-la.

Groxx
fonte
3

Uma maneira mais "tipográfica de digitação" é usar respond_to?dessa maneira as classes "tipo inteiro" ou "tipo string" também podem ser usadas

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

No caso de você não precisa converter os valores zero, eu encontrar os métodos to_ie to_fser extremamente útil, uma vez que irá converter a string para qualquer um valor zero (se não conversíveis ou zero) ou o real Integerou Floatvalor.

"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: cuidado, o 0valor inteiro não é falsey; é verdade ( !!0 #=> true) (obrigado @prettycoder)

EDITAR

Ah, descobri os casos escuros ... parece que só acontece se o número estiver na primeira posição

"12blah".to_i => 12
Cyril Duchon-Doris
fonte
0 é verdade em rubi!
precisa saber é o seguinte
1
@prettycoder graças a cabeça para cima, eu vou corrigir isso imediatamente na resposta
Cyril Duchon-Doris
1

Para capitalizar a resposta de Alex D , usando refinamentos :

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

Mais tarde, na sua classe:

require 'core_ext/string/integerable'

class MyClass
  using CoreExtensions::Integerable

  def method
    'my_string'.integer?
  end
end
Vadym Tyemirov
fonte
0

Eu tive um problema semelhante antes de tentar determinar se algo é uma string ou qualquer tipo de número. Eu tentei usar uma expressão regular, mas isso não é confiável para o meu caso de uso. Em vez disso, você pode verificar a classe da variável para ver se é uma descendente da classe Numérica.

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

Nessa situação, você também pode substituir qualquer um dos descendentes numéricos: BigDecimal, Date :: Infinity, Inteiro, Fixnum, Float, Bignum, Rational, Complex

penguincoder
fonte
-1

Provavelmente você está procurando algo parecido com isto:

Aceite "2.0 ou 2.0 como INT, mas rejeite 2.1 e" 2.1 "

num = 2.0

se num.is_a? String num = final falso de resgate flutuante (num) (num)

new_num = Resgate inteiro (num) false

coloca num

coloca new_num

coloca num == new_num

Owais Akbani
fonte