2014-07-27 12 views
30

Do programowania stron internetowych liczby są podawane jako ciągi. ale to_i zamieni "5abc" na 5 i "abc" na 0, obie złe odpowiedzi. Złapać je, pisałem:Ściśle przekształcić ciąg na liczbę całkowitą (lub zero)

def number_or_nil(s) 
    number = s.to_i 
    number = nil if (number.to_s != s) 
    return number 
end 

Czy istnieje neater, Ruby bardziej naturalny sposób realizacji tej konwersji i wykrycie, że ciąg nie został pomyślany jako liczby?

+0

'' 5 ''powinno być' 5' lub 'zero'? –

+0

Pytanie nie jest jasne. Co jest nie tak z 'to_i'? Co to jest "ta konwersja"? – sawa

+0

nil jest tym, czego bym się spodziewał, chociaż prawdopodobnie mogę żyć z 5. –

Odpowiedz

56

Korzystanie Integer (string)

będzie podnieść błąd ArgumentError jeśli ciąg nie można przekonwertować na liczbę całkowitą.

Integer('5abc') #=> ArgumentError: invalid value for Integer(): "5abc" 
Integer('5') #=> 5 

Można by jeszcze trzeba metodę number_or_nil jeśli chcesz zachowanie się, że zero jest zwracany, gdy łańcuch nie mogą być konwertowane.

def number_or_nil(string) 
    Integer(string || '') 
rescue ArgumentError 
    nil 
end 

Należy zachować ostrożność, aby uratować od określonego wyjątku. Nagie ratowanie (takie jak "zero ratunkowe") uratuje przed każdym błędem, który dziedziczy po StandardError i może zakłócać wykonanie twojego programu w sposób, jakiego się nie spodziewasz. Integer() spowoduje zgłoszenie ArgumentError, więc należy to określić.

Jeśli raczej nie radzić sobie z wyjątkami i po prostu wolą krótszą wersję swojej number_or_nil można skorzystać z wartości zwracanych ukrytych i zapisać go jako:

def number_or_nil(string) 
    num = string.to_i 
    num if num.to_s == string 
end 

number_or_nil '5' #=> 5 
number_or_nil '5abc' #=> nil 

To będzie działać zgodnie z oczekiwaniami.

+3

Jedyne zastrzeżenie to 'Integer (zero)' powoduje 'TypeError', więc' Integer (ciąg || '') 'jest bardziej spójny. – RocketR

+0

Dobry punkt @RocketR! –

+1

Gdzie mogę znaleźć (oficjalną) dokumentację dla 'Integer (string)'? O ile widzę, nie ma o tym wzmianki w oficjalnej dokumentacji [ruby 'Integer'] (http://ruby-doc.org/core-2.2.3/Integer.html). – apepper

0

Użyj prostego wyrażenia regularnego do sprawdzenia, czy str jest liczbą całkowitą.

def number_or_nil(str) 
    str.to_i if str[/^-?\d+$/] and str.line.size == 1 
end 
+0

Ponieważ dane wejściowe pochodzą z internetu, powinieneś zmienić swoją odpowiedź, aby oczekiwać wielu treść liniowa. str.to_i jeśli str [/ \ A \ d + \ z /] –

+0

Negatywne liczby całkowite, białe znaki? –

+0

Naprawiono. Ja check oczekuje ścisłych reguł dla liczb całkowitych, bez białych znaków, bez znaków nowej linii. – hakcho