Comprobando si una variable es un número entero

137

¿Rails 3 o Ruby tienen una forma integrada de verificar si una variable es un entero?

Por ejemplo,

1.is_an_int #=> true
"[email protected]".is_an_int #=> false?
Un aprendiz
fuente
posible duplicado de ¿Tiene ruby ​​1.9.2 un is_a? ¿función?
Andrew Grimm
1
En lugar de preocuparse si una variable es un número entero, debe verificar si la variable responde to_i. Eso es parte del "tipeo de pato" de Ruby: si puede actuar como un número entero, trátelo como tal.
The Tin Man
44
@ The Tin Man: No del todo. "hola" .to_i devuelve 0, que puede no ser lo que esperas.
EinLama
1
@AnApprentice Para su información, kind_of?es un alias para is_a?.
Jacob Relkin el
3
@JacobRelkin is_a?es ligeramente diferente; pregunta si el objeto de una instancia de una clase específica; kind_of?pregunta si es una instancia o hijo de una clase específica. fido.is_a? Doges verdad; fido.kind_of? AnimalEs cierto, por ejemplo.
Tom Harrison

Respuestas:

274

Puedes usar el is_a?método

>> 1.is_a? Integer
=> true
>> "[email protected]".is_a? Integer
=> false
>> nil.is_a? Integer
=> false
mportiz08
fuente
2
Eso es genial. ¿Funciona eso para validar las direcciones de correo electrónico?
AnApprentice
65
@AnApprentice ¿Desde cuándo validar las direcciones de correo electrónico es parte de la pregunta?
Jacob Relkin el
44
esto no funcionará si el número viene en una cadena como "11111111"
Ricbermo
mire abajo Integer(obj) rescue false Esto no funcionará para "1" si desea verificar si se convertirá
mc.
44
@Ricbermo "1111111" es una cadena. Una cadena que resulta ser convertible e Integer.
Sqeaky
50

Si desea saber si un objeto es un objeto Integer o algo que se puede convertir de manera significativa en un entero (sin incluir cosas como "hello", que to_ise convertirá a 0):

result = Integer(obj) rescue false
Alex D
fuente
2
Tal vez solo soy un novato, pero este ajuste me habría ayudado. resultado = Integer (obj) rescate falso.
John Curry
@ JohnCurry, siéntase libre de editar la respuesta si puede mejorarla. Así es como funciona SO.
Alex D
2
Lo hice, fue rechazado. "Esta edición se desvía de la intención original de la publicación" Pero independientemente, gracias por su respuesta, ¡me ayudó a resolver mi problema!
John Curry
77
Integer ('08 ') fallará debido a que la cadena se interpreta como octal, Integer ('08', 10) funciona bien. Por si acaso.
Jong Bor Lee
1
No estoy seguro si Integer(2.5) => 2siempre es una conversión significativa.
mkataja
29

Use una expresión regular en una cadena:

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

Si desea verificar si una variable es de cierto tipo, simplemente puede usar kind_of?:

1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545"  #true
is_numeric? "2aa"  #false
Jacob Relkin
fuente
¿Esto es exactamente lo que estaba buscando el is_numeric?
workdreamer
Creo que esto está cerca, pero no es exactamente correcto. Por ejemplo, fallará para ".34". El problema, creo, es que en \d+?el ?especifica una coincidencia no codiciosa, mientras que probablemente quieras una coincidencia opcional. Cambiar \d+?a \d*podría solucionarlo, pero me gustaría ejecutarlo a través de un conjunto de pruebas para estar seguro. Esto tampoco coincidirá con la notación hexadecimal o exponencial, pero estoy seguro de que está bien para ciertos casos de uso.
Jeff
1
¿Por qué no solo usar esta expresión regular \A\d+\z:?
NARKOZ
1
Compare con el Integer(obj) rescue falsecódigo de @ alex-d a continuación; regexp es difícil de leer y no está claro en su intención. Ambos funcionan, llegué a esta pregunta en un intento de arreglar una expresión regular mal construida que no siempre funcionaba :-)
Tom Harrison
17

Si no está seguro del tipo de la variable (podría ser una cadena de caracteres numéricos), digamos que era un número de tarjeta de crédito que se pasó a los parámetros, por lo que originalmente sería una cadena pero desea asegurarse de que no No tiene ninguna letra, yo usaría 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 señala un descuido de este método, tenga esto en cuenta:

is_number? "01" # false. oops!
papa grande
fuente
Gracias, me salvas el día. Para cualquiera que necesite verificar si flota o no, puede cambiar directamente a obj.to_s == obj.to_f.to_sigual que en mi caso.
ksugiarto
¡Edmund es listo! 🙌
siwalikm
Impresionante, prefiero esto que Integer ('123fh') y excepción de rescate.
zw963
6

Puedes usar triple igual.

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

Hay var.is_a? Class(en su caso:) var.is_a? Integer; eso podría encajar en la factura. O hay Integer(var), donde arrojará una excepción si no puede analizarlo.

Groxx
fuente
3

Una forma más de "escribir pato" es usar de respond_to?esta manera las clases "tipo entero" o "tipo cadena".

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

En caso de que no es necesario convertir los valores cero, encuentro los métodos to_iy to_fser de gran utilidad ya que serán convertir la cadena ya sea a un valor cero (si no convertible o cero) o el real Integero 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: tenga cuidado, el 0valor entero no es falso, es verdadero ( !!0 #=> true) (gracias @prettycoder)

EDITAR

Ah, acabo de enterarme de los casos oscuros ... aunque parece que solo sucede si el número está en primera posición

"12blah".to_i => 12
Cyril Duchon-Doris
fuente
¡0 es veraz en rubí!
Prettycoder
1
@prettycoder gracias por el aviso, arreglaré esto inmediatamente en la respuesta
Cyril Duchon-Doris
1

Para capitalizar la respuesta de Alex D , usando refinamientos :

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

Más tarde, en tu clase:

require 'core_ext/string/integerable'

class MyClass
  using CoreExtensions::Integerable

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

He tenido un problema similar antes de intentar determinar si algo es una cadena o cualquier tipo de número. He intentado usar una expresión regular, pero eso no es confiable para mi caso de uso. En su lugar, puede verificar la clase de la variable para ver si es un descendiente de la clase Numérica.

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

En esta situación, también puede sustituir cualquiera de los descendientes numéricos: BigDecimal, Date :: Infinity, Integer, Fixnum, Float, Bignum, Rational, Complex

penguincoder
fuente
-1

Probablemente estés buscando algo como esto:

Acepte "2.0 o 2.0 como INT pero rechace 2.1 y" 2.1 "

num = 2.0

si num.is_a? Cadena num = Float (num) rescate falso final

new_num = Integer (num) rescate falso

pone num

pone new_num

pone num == new_num

Owais Akbani
fuente