2011-01-04 23 views
107

Czy Rails 3 lub Ruby mają wbudowany sposób sprawdzenia, czy zmienna jest liczbą całkowitą?Sprawdzanie, czy zmienna jest liczbą całkowitą

Na przykład

1.is_an_int #=> true 
"[email protected]".is_an_int #=> false? 
+0

możliwy duplikat z [Czy ruby ​​1.9.2 mają is_a? funkcji?] (http://stackoverflow.com/questions/4282273/does-ruby-1-9-2-have-an-is-a-function) –

+1

Zamiast dbać o to, czy zmienna jest liczbą całkowitą, należy sprawdzić aby sprawdzić, czy zmienna odpowiada na 'to_i'. To część "pisania na klawiaturze" Rubiego: jeśli może działać jak liczba całkowita, potraktuj to jak jedną. –

+4

@ The Tin Man: Nie całkowicie. "hello" .to_i zwraca 0, co może nie być tym, czego oczekujesz. – EinLama

Odpowiedz

230

Można użyć metody

>> 1.is_a? Integer 
=> true 
>> "[email protected]".is_a? Integer 
=> false 
>> 
+1

To bardzo fajne. czy to działa, aby sprawdzić poprawność adresów e-mail? – AnApprentice

+54

@AnApprentice Od kiedy sprawdzanie poprawności adresów e-mail stanowi część pytania? –

+1

to przyzwyczajenie praca, jeśli numer jest w ciągu znaków takich jak „11111111” – Ricbermo

28

użyć wyrażenia regularnego na sznurku:

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

Jeśli chcesz sprawdzić, czy zmienna jest określonego typu, można po prostu wykorzystać kind_of?:

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

To jest dokładnie to, czego szukałem is_numeric? – workdreamer

+0

Myślę, że jest blisko, ale nie do końca. Na przykład nie powiedzie się dla ".34". Problem, jak sądzę, polega na tym, że w '\ d +?' '?' Określa nie-zachłanne dopasowanie, podczas gdy prawdopodobnie chcesz opcjonalne dopasowanie. Zmiana '\ d +?' Na '\ d *' może go naprawić, ale chciałbym go przeprowadzić poprzez zestaw testów, aby mieć pewność. To również nie będzie zgodne z notacją szesnastkową ani wykładniczą, ale jestem pewien, że jest to dobre w przypadku niektórych przypadków użycia. – Jeff

+1

Dlaczego po prostu nie używać tego wyrażenia regularnego: '\ A \ d + \ z'? – NARKOZ

5

Jest var.is_a? Class (w twoim przypadku: var.is_a? Integer); to może pasować do rachunku. Albo jest Integer(var), gdzie wyrzuci wyjątek, jeśli nie może go przetworzyć.

3

Bardziej „kaczka wpisując” sposobem jest użycie respond_to? ten sposób zajęcia „całkowitymi-like” lub „string-like” mogą być również wykorzystywane

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

Jeśli nie masz pewności co do rodzaju zmiennej (może to być ciąg znaków liczbowych), powiedz, że był to numer karty kredytowej przekazywany do parametrów, więc początkowo byłby ciągiem znaków, ale chcesz się upewnić nie ma w nim żadnych znaków literowych, użyłbym tego hod:

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

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

@Benny zaznacza przeoczenie tej metody, tym pamiętać:

is_number? "01" # false. oops! 
+0

dzięki, oszczędzasz mój dzień. Dla każdego, kto chce sprawdzić, czy pływa, czy nie, może zmienić się bezpośrednio na "obj.to_s == obj.to_f.to_s", tak jak w moim przypadku. – ksugiarto

43

Jeśli chcesz wiedzieć, czy dany przedmiot jest Integerlub coś, co można sensownie przekonwertowany do Integer (nie wliczając rzeczy jak "hello"to_i, która będzie konwertować do 0):

result = Integer(obj) rescue false 
+2

Może jestem po prostu noobem, ale ta korekta pomogłaby mi. wynik = liczba całkowita (obj) ratowanie fałszywe. –

+0

@JohnCurry, możesz edytować odpowiedź, jeśli możesz ją poprawić. Tak działa SO. –

+2

Zrobiłem, został odrzucony. "Ta zmiana odbiega od pierwotnej intencji postu". Ale niezależnie, dziękuję za odpowiedź, pomogło mi to rozwiązać mój problem! –

0

Miałem podobny problem, zanim spróbuję ustalić, czy coś jest ciągiem znaków lub jakimkolwiek numerem. Próbowałem użyć wyrażenia regularnego, ale nie jest to niezawodne dla mojego przypadku użycia. Zamiast tego możesz sprawdzić klasę zmiennej, aby zobaczyć, czy jest potomkiem klasy Numeric.

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

W tej sytuacji, można również zastąpić każdy z potomków numeryczne: BigDecimal, Date :: nieskończoność, Integer Fixnum, pływak, Bignum, racjonalne, złożone

2

Można użyć potrójnego równe.

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

wykorzystać the answer of Alex D korzystając refinements:

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

Później w was Klasa:

require 'core_ext/string/integerable' 

class MyClass 
    using CoreExtensions::Integerable 

    def method 
    'my_string'.integer? 
    end 
end 
2

W przypadku, gdy nie trzeba konwertować wartości zerowe, uważam, że metody to_i i to_f są niezwykle użyteczne, ponieważ przekształcą ciąg znaków w wartość zero (jeśli nie są wymienialne lub zero) lub wartość tual Integer lub 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 

I jak teraz, wartość 0 jest falsey dzięki czemu może być stosowany w warunkowych

"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" 

znajdę to zachowanie bardzo pomocne, ponieważ będzie używać logiki konwersji wszystkich Ruby i często w moim logiki 0 przypadek jest stosowany jako falsey zresztą

EDIT

Ach właśnie dowiedział się o ciemnych sprawach ... wydaje się tylko wtedy, gdy numer jest na pierwszym miejscu chociaż

"12blah".to_i => 12 
0

Prawdopodobnie szukasz czegoś takiego:

Akceptuj „2.0 lub 2.0 jako int ale odrzucają 2.1 i "2.1"

num = 2,0

jeśli num.is_a? String num = float (num) ratowanie fałszywy koniec

new_num = Integer (num) ratowanie fałszywe

stawia Num

stawia new_num

puts num == new_num

Powiązane problemy