Mam następujący kontroler aplikacji:
def is_number?(object)
true if Float(object) rescue false
end
i następujący warunek w moim kontrolerze:
if mystring.is_number?
end
Warunek generuje undefined method
błąd. Zgaduję, że zdefiniowałem is_number
w złym miejscu ...?
ruby-on-rails
ruby
string
integer
Jamie Buchanan
źródło
źródło
Odpowiedzi:
Utwórz
is_number?
metodę.Utwórz metodę pomocniczą:
A potem nazwij to tak:
Rozszerz
String
klasę.Jeśli chcesz mieć możliwość wywołania
is_number?
bezpośrednio ciągu zamiast przekazywania go jako parametru do funkcji pomocniczej, musisz zdefiniowaćis_number?
jako rozszerzenieString
klasy, na przykład:A potem możesz to nazwać:
źródło
to_f
w powyższym, a Float () nie wykazuje tego zachowania:Float("330.346.11")
podbijaArgumentError: invalid value for Float(): "330.346.11"
lib/core_ext/string.rb
.is_number?(string)
bit działał Ruby 1.9. Może to część Railsów lub 1.8?String.is_a?(Numeric)
Pracuje. Zobacz także stackoverflow.com/questions/2095493/… .Oto punkt odniesienia dla typowych sposobów rozwiązania tego problemu. Zwróć uwagę, który z nich powinien być używany, zależy prawdopodobnie od oczekiwanego współczynnika fałszywych przypadków.
Jeśli wydajność nie ma znaczenia, użyj tego, co lubisz. :-)
Szczegóły sprawdzania liczb całkowitych:
Szczegóły sprawdzania pływaka:
źródło
źródło
/^\d+$/
nie jest bezpiecznym wyrażeniem regularnym w Rubim,/\A\d+\Z/
jest. (np. zwróci „42 \ nktóry tekst”true
)/^\d+$/
przypadku linii, ale w tym przypadku dotyczy to początku i końca łańcucha/\A\d+\Z/
.Poleganie na podniesionym wyjątku nie jest najszybszym, czytelnym ani niezawodnym rozwiązaniem.
Zrobiłbym co następuje:
źródło
expect(my_string).to match(/^[0-9]+$/)
my_string =~ /\A-?(\d+)?\.?\d+\Z/
pozwala ci zrobić „.1”, „-0,1” lub „12”, ale nie „”, „-” lub „”.Począwszy od Rubiego 2.6.0, numeryczne metody rzutowania mają opcjonalny
exception
-argument [1] . Dzięki temu możemy używać wbudowanych metod bez używania wyjątków jako przepływu sterowania:Dlatego nie musisz definiować własnej metody, ale możesz bezpośrednio sprawdzać zmienne, takie jak np
źródło
tak to robię, ale myślę, że musi być lepszy sposób
źródło
object = "1.2e+35"; object.to_f.to_s == object
i zadziałałonie, po prostu źle go używasz. twój numer_jest? ma argument. nazwałeś to bez argumentu
powinieneś zrobić is_number? (mystring)
źródło
mystring
rzeczywiście jest Stringiem,mystring.is_a?(Integer)
zawsze będzie false. Wygląda na to, że chce wyniku takiego jakis_number?("12.4") #=> true
Tl; dr: Użyj podejścia regex. Jest 39 razy szybsza niż metoda ratunkowa w przyjętej odpowiedzi, a także obsługuje przypadki typu „1000”
-
Zaakceptowana odpowiedź @Jakob S w większości działa, ale wyłapywanie wyjątków może być naprawdę powolne. Ponadto metoda ratunkowa zawodzi w przypadku łańcucha takiego jak „1000”.
Zdefiniujmy metody:
A teraz kilka przypadków testowych:
I mały kod do uruchamiania przypadków testowych:
Oto wynik przypadków testowych:
Czas na testy wydajności:
A wyniki:
źródło
5.4e-29
. Domyślam się, że twoje wyrażenie regularne można zmodyfikować, aby akceptować również te.W railsach 4 musisz umieścić
require File.expand_path('../../lib', __FILE__) + '/ext/string'
swój config / application.rbźródło
Jeśli wolisz nie używać wyjątków jako części logiki, możesz spróbować tego:
Albo, jeśli chcesz go do pracy we wszystkich klas obiektów, wymienić
class String
zclass Object
na siebie Konwersja na ciąg znaków:!!(self.to_s =~ /^-?\d+(\.\d*)?$/)
źródło
nil?
zera jest trurthy na rubin, więc można zrobić tylko!!(self =~ /^-?\d+(\.\d*)?$/)
!!
pewnością działa. Co najmniej jeden przewodnik po stylu Ruby ( github.com/bbatsov/ruby-style-guide ) sugerował unikanie!!
na korzyść.nil?
czytelności, ale widziałem, że jest!!
używany w popularnych repozytoriach i myślę, że jest to dobry sposób na konwersję na boolean. Zmieniłem odpowiedź.użyj następującej funkcji:
więc,
is_numeric? "1.2f"
= fałszis_numeric? "1.2"
= prawdais_numeric? "12f"
= fałszis_numeric? "12"
= prawdaźródło
"0"
. Zwróć również uwagę, że metoda.try
nie jest częścią podstawowej biblioteki Ruby i jest dostępna tylko wtedy, gdy używasz ActiveSupport."12"
, więc Twój czwarty przykład w tym pytaniu jest błędny."12.10"
i"12.00"
też nie.Jak głupie jest to rozwiązanie?
źródło