2013-08-30 13 views
11

Ho una colonna di Excel che contiene i numeri di parte. Ecco un esempioTaglia un trailing .0

Come si può vedere, può essere molti tipi di dati diversi: Float, Int e String. Sto usando roo gem per leggere il file. Il problema è che roo interpreta celle intere come Float, aggiungendo uno zero finale a esse (16431 => 16431.0). Voglio tagliare questo zero finale. Non riesco a utilizzare to_i perché ridurrà tutti i numeri finali delle celle che richiedono un decimale in loro (la prima riga nell'esempio precedente) e taglierà tutto dopo un carattere stringa nelle righe String (l'ultima riga dell'esempio precedente).

Attualmente, ho un metodo che controlla gli ultimi due caratteri della cellula e li rifila se sono" .0"

def trim(row) 
    if row[0].to_s[-2..-1] == ".0" 
     row[0] = row[0].to_s[0..-3] 
    end 
end 

Questo funziona, ma ci si sente terribile e hacky. Qual è il modo corretto di ottenere il contenuto del mio file Excel in una struttura dati Ruby?

risposta

40
def trim num 
    i, f = num.to_i, num.to_f 
    i == f ? i : f 
end 

trim(2.5) # => 2.5 
trim(23) # => 23 

o, da stringa:

def convert x 
    Float(x) 
    i, f = x.to_i, x.to_f 
    i == f ? i : f 
rescue ArgumentError 
    x 
end 

convert("fjf") # => "fjf" 
convert("2.5") # => 2.5 
convert("23") # => 23 
convert("2.0") # => 2 
convert("1.00") # => 1 
convert("1.10") # => 1.1 
+1

o solo risultato = result.to_i se risultato == result.to_i – peter

0

Prova:

"16431.0".to_i 
#=> 16431 
+1

non posso usare 'to_i' perché ho bisogno di mantenere le qualità galleggiante di cellule che in realtà hanno un numero decimale in loro. Domanda aggiornata. –

+0

@DanGarman Capisco che questa risposta non soddisfi i tuoi bisogni, ma il tuo "assetto" non lo è altrettanto. Restituisce 'nil' quando il float non deve essere convertito in un numero intero. – sawa

+0

Perché giù voto? La mia risposta non era sbagliata, la domanda non menzionava questo requisito ... –

-1

Numeric values are returned as type :float

def convert_cell(cell) 
    if cell.is_a?(Float) 
    i = cell.to_i 
    cell == i.to_f ? i : cell 
    else 
    cell 
    end 
end 

convert_cell("foobar") # => "foobar" 
convert_cell(123) # => 123 
convert_cell(123.4) # => 123.4 
+0

È uguale alla prima parte della mia risposta, tranne che non si esegue la memoizzazione. – sawa

+0

corretto. non l'ho visto quando ho iniziato a scrivere. Modificato ora. – jomo

+0

'convert_string (" 1.00 ") # =>" 1.00 "', 'convert_string (" 1.20 ") # =>" 1.20 "' – sawa

15

ActionView dispone di metodi number_with_precision che prende uno strip_insignificant_zeros: vero argomento che gestisce questo.

number_with_precision(13.00, precision: 2, strip_insignificant_zeros: true) 
# => 13 
number_with_precision(13.25, precision: 2, strip_insignificant_zeros: true) 
# => 13.25 

http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_precision

+1

Questa dovrebbe essere la risposta accettata – bpercevic

0

Questo dovrebbe coprire le esigenze nella maggior parte dei casi: some_value.gsub(/(\.)0+$/, '')

E Modifica gli zeri finali e un punto decimale seguito solo da zeri. Altrimenti, lascia la stringa da solo.

È anche molto performante, poiché è interamente basato su stringhe, non richiede conversioni in virgola mobile o intera. (Assumendo che il valore di ingresso è già una stringa)

Loading development environment (Rails 3.2.19) 
irb(main):001:0> '123.0'.gsub(/(\.)0+$/, '') 
=> "123" 
irb(main):002:0> '123.000'.gsub(/(\.)0+$/, '') 
=> "123" 
irb(main):003:0> '123.560'.gsub(/(\.)0+$/, '') 
=> "123.560" 
irb(main):004:0> '123.'.gsub(/(\.)0+$/, '') 
=> "123." 
irb(main):005:0> '123'.gsub(/(\.)0+$/, '') 
=> "123" 
irb(main):006:0> '100'.gsub(/(\.)0+$/, '') 
=> "100" 
irb(main):007:0> '127.0.0.1'.gsub(/(\.)0+$/, '') 
=> "127.0.0.1" 
irb(main):008:0> '123xzy45'.gsub(/(\.)0+$/, '') 
=> "123xzy45" 
irb(main):009:0> '123xzy45.0'.gsub(/(\.)0+$/, '') 
=> "123xzy45" 
irb(main):010:0> 'Bobby McGee'.gsub(/(\.)0+$/, '') 
=> "Bobby McGee" 
irb(main):011:0>