2014-07-27 17 views
30

Per la programmazione Web, i numeri vengono come stringhe. ma to_i convertirà "5abc" a 5 e "abc" a 0, entrambe le risposte sbagliate. Per catturare questi, ho scritto:Converte rigorosamente stringa in intero (o nullo)

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

Esiste un più ordinato, modo più Rubino naturale di realizzare questa conversione e rilevando che la stringa non è stato inteso come un numero?

+0

''5'' deve essere '5' o' nil'? –

+0

La domanda non è chiara. Cosa c'è di sbagliato in 'to_i'? Cos'è "questa conversione"? – sawa

+0

nil è quello che mi aspetterei, anche se probabilmente posso vivere con 5. –

risposta

56

Usa Integer (stringa)

Si genererà un errore ArgumentError se la stringa non può convertire in un numero intero.

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

saresti ancora bisogno del vostro metodo di number_or_nil se si desidera che il comportamento sia che nullo viene restituito quando una stringa non può essere convertito.

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

Si dovrebbe fare attenzione a salvare da una particolare eccezione. Un salvataggio nullo (come "rescue nil") salverà da qualsiasi errore che erediti da StandardError e potrebbe interferire con l'esecuzione del programma in modi che non ti aspetti. Integer() genererà un ArgumentError, quindi specificalo.

Se si preferisce non trattare con le eccezioni e solo preferisce una versione più breve del vostro number_or_nil è possibile usufruire dei valori di ritorno impliciti e scrivere come:

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 

Ciò funzionerà nel modo previsto.

+3

Unica avvertenza è 'Integer (nil)' solleva 'TypeError', quindi' Integer (string || '') 'è più coerente. – RocketR

+0

Buon punto @RocketR! –

+1

Dove posso trovare la documentazione (ufficiale) per 'Integer (stringa)'? Per quanto posso vedere, non c'è menzione nella documentazione ufficiale [ruby 'Integer'] (http://ruby-doc.org/core-2.2.3/Integer.html). – apepper

0

Utilizzare una semplice espressione regolare per verificare str è un numero intero.

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

Poiché l'input proviene dal web, dovresti cambiare la tua contenuto di linea. str.to_i if str [/ \ A \ d + \ z /] –

+0

Numeri interi negativi, spazi bianchi? –

+0

risolto. Me check si aspetta regole rigide per numeri interi, senza spazi bianchi, niente righe nuove. – hakcho