Überprüfen, ob eine Variable eine Ganzzahl ist

137

Verfügt Rails 3 oder Ruby über eine integrierte Methode, um zu überprüfen, ob eine Variable eine Ganzzahl ist?

Beispielsweise,

1.is_an_int #=> true
"[email protected]".is_an_int #=> false?
Ein Lehrling
quelle
Mögliches Duplikat von Hat Ruby 1.9.2 ein is_a? Funktion?
Andrew Grimm
1
Anstatt sich darum zu kümmern, ob eine Variable eine Ganzzahl ist, sollten Sie überprüfen, ob die Variable darauf reagiert to_i. Das ist Teil von Rubys "Ententypisierung": Wenn es sich wie eine ganze Zahl verhalten kann, behandeln Sie es wie eine.
der Blechmann
4
@ the Tin Man: Nicht ganz. "hallo" .to_i gibt 0 zurück, was möglicherweise nicht Ihren Erwartungen entspricht.
EinLama
1
@AnApprentice Zu Ihrer Information kind_of?ist ein Alias ​​zu is_a?.
Jacob Relkin
3
@JacobRelkin is_a?ist etwas anders; es fragt, ob das Objekt einer Instanz einer bestimmten Klasse; kind_of?fragt, ob es sich um eine Instanz oder ein Kind einer bestimmten Klasse handelt. fido.is_a? Dogist wahr; fido.kind_of? Animalist zum Beispiel wahr.
Tom Harrison

Antworten:

274

Sie können die is_a?Methode verwenden

>> 1.is_a? Integer
=> true
>> "[email protected]".is_a? Integer
=> false
>> nil.is_a? Integer
=> false
mportiz08
quelle
2
Das ist sehr cool. funktioniert das, um E-Mail-Adressen zu validieren?
AnApprentice
65
@AnApprentice Seit wann war die Überprüfung von E-Mail-Adressen Teil der Frage?
Jacob Relkin
4
Dies funktioniert nicht, wenn die Nummer in einer Zeichenfolge wie "11111111"
Ricbermo
siehe unten Integer(obj) rescue false Dies funktioniert nicht für "1", wenn Sie überprüfen möchten, ob es konvertiert
mc.
4
@ Ricbermo "1111111" ist ein String. Ein String, der zufällig in und Integer konvertierbar ist.
Sqeaky
50

Wenn Sie wissen möchten, ob es sich bei einem Objekt um ein Objekt handelt Integer oder um ein Objekt , das sinnvoll in eine Ganzzahl konvertiert werden kann (ohne Dinge wie die "hello", in die to_ikonvertiert werden soll 0):

result = Integer(obj) rescue false
Alex D.
quelle
2
Vielleicht bin ich nur ein Noob, aber diese Optimierung hätte mir geholfen. Ergebnis = Ganzzahl (obj) Rettung falsch.
John Curry
@ JohnCurry, zögern Sie nicht, die Antwort zu bearbeiten, wenn Sie sie verbessern können. So funktioniert SO.
Alex D
2
Ich habe es abgelehnt. "Diese Bearbeitung weicht von der ursprünglichen Absicht des Beitrags ab." Aber trotzdem, danke für Ihre Antwort, es hat mir geholfen, mein Problem zu lösen!
John Curry
7
Integer ('08 ') schlägt fehl, da die Zeichenfolge als oktal interpretiert wird. Integer ('08', 10) funktioniert einwandfrei. Nur für den Fall.
Jong Bor Lee
1
Ich bin mir nicht sicher, ob Integer(2.5) => 2es sich immer um eine sinnvolle Konvertierung handelt.
mkataja
29

Verwenden Sie einen regulären Ausdruck für eine Zeichenfolge:

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

Wenn Sie überprüfen möchten, ob eine Variable von einem bestimmten Typ ist, können Sie einfach Folgendes verwenden kind_of?:

1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545"  #true
is_numeric? "2aa"  #false
Jacob Relkin
quelle
Dies ist genau das, wonach ich nach der is_numeric gesucht habe?
Workdreamer
Ich denke, das ist nah, aber nicht genau richtig. Zum Beispiel wird es für ".34" fehlschlagen. Das Problem, denke ich, ist, dass in \d+?der ?spezifiziert eine nicht gierige Übereinstimmung, während Sie wahrscheinlich eine optionale Übereinstimmung wollen. Das Ändern \d+?in \d*könnte das Problem beheben, aber ich möchte es sicherheitshalber durch eine Reihe von Tests führen. Dies stimmt auch nicht mit der Hex- oder Exponentialschreibweise überein, aber ich bin sicher, dass dies für bestimmte Anwendungsfälle in Ordnung ist.
Jeff
1
Warum nicht einfach diesen regulären Ausdruck verwenden : \A\d+\z?
NARKOZ
1
Vergleiche mit dem Integer(obj) rescue falseCode von @ alex-d unten; Regexp ist schwer zu lesen und in seiner Absicht nicht klar. Bei beiden Arbeiten kam ich zu dieser Frage, um einen schlecht konstruierten regulären Ausdruck zu beheben, der nicht immer funktionierte :-)
Tom Harrison
17

Wenn Sie sich über den Typ der Variablen nicht sicher sind (es kann sich um eine Zeichenfolge mit Zahlen handeln), sagen Sie, dass es sich um eine Kreditkartennummer handelt, die an die Parameter übergeben wurde. Es handelt sich also ursprünglich um eine Zeichenfolge, aber Sie möchten sicherstellen, dass dies nicht der Fall ist. ' Wenn keine Buchstaben enthalten sind, würde ich diese Methode verwenden:

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

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

@Benny weist auf ein Versehen dieser Methode hin, denken Sie daran:

is_number? "01" # false. oops!
Bigpotato
quelle
Danke, du rettest meinen Tag. Für alle, die prüfen müssen, ob es schwebt oder nicht, kann sich direkt ändern, obj.to_s == obj.to_f.to_sgenau wie in meinem Fall.
ksugiarto
Edmund, das ist klug! 🙌
Siwalikm
Genial, ich bevorzuge dies als Integer ('123fh') und Rettungsausnahme.
zw963
6

Sie können Triple Equal verwenden.

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

Es gibt var.is_a? Class(in Ihrem Fall :) var.is_a? Integer; das könnte die Rechnung passen. Oder es gibt eine Stelle Integer(var), an der eine Ausnahme ausgelöst wird, wenn sie nicht analysiert werden kann.

Groxx
quelle
3

Eine "Enten-Typisierung" -Methode besteht darin, auf respond_to?diese Weise auch "ganzzahlige" oder "stringartige" Klassen zu verwenden

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

Für den Fall , müssen Sie keine Null - Werte konvertieren, ich die Methoden finden to_iund to_fäußerst nützlich sein , da sie die Zeichenfolge entweder auf einen Null - Wert konvertieren (wenn nicht konvertierbar oder Null) oder der tatsächlichen Integeroder FloatWert.

"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: Sei vorsichtig, der 0ganzzahlige Wert ist nicht falsch, er ist wahr ( !!0 #=> true) (danke @prettycoder)

BEARBEITEN

Ich habe gerade von den dunklen Fällen erfahren ... scheint nur zu passieren, wenn die Nummer an erster Stelle steht

"12blah".to_i => 12
Cyril Duchon-Doris
quelle
0 ist wahr in Rubin!
Prettycoder
1
@ Prettycoder danke für das Heads-up, ich werde dies sofort in der Antwort beheben
Cyril Duchon-Doris
1

Um die Antwort von Alex D mit Verfeinerungen zu nutzen :

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

Später in deiner Klasse:

require 'core_ext/string/integerable'

class MyClass
  using CoreExtensions::Integerable

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

Ich hatte ein ähnliches Problem, bevor ich versuchte festzustellen, ob es sich bei etwas um eine Zeichenfolge oder eine beliebige Zahl handelt. Ich habe versucht, einen regulären Ausdruck zu verwenden, aber das ist für meinen Anwendungsfall nicht zuverlässig. Stattdessen können Sie die Klasse der Variablen überprüfen, um festzustellen, ob sie ein Nachkomme der numerischen Klasse ist.

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

In dieser Situation können Sie auch einen der numerischen Nachkommen ersetzen: BigDecimal, Date :: Infinity, Integer, Fixnum, Float, Bignum, Rational, Complex

Pinguincoder
quelle
-1

Wahrscheinlich suchen Sie so etwas:

Akzeptieren Sie "2.0 oder 2.0 als INT, lehnen Sie jedoch 2.1 und" 2.1 "ab.

num = 2,0

wenn num.is_a? String num = Float (num) rettet falsches Ende

new_num = Integer (num) Rescue false

setzt num

setzt new_num

setzt num == new_num

Owais Akbani
quelle