Domanda

Sto cercando un modo conciso per verificare un valore per vedere se è zero o zero. Attualmente sto facendo qualcosa del tipo:

if (!val || val == 0)
  # Is nil or zero
end

Ma questo sembra molto goffo.

È stato utile?

Soluzione

Gli oggetti hanno un zero? metodo .

if val.nil? || val == 0
  [do something]
end

Oppure, per una sola istruzione:

[do something] if val.nil? || val == 0

Altri suggerimenti

Se ti piacciono davvero i nomi dei metodi con punti interrogativi alla fine:


if val.nil? || val.zero?
  # do stuff
end

La tua soluzione va bene, così come alcune delle altre soluzioni.

Ruby può farti cercare un modo carino di fare tutto, se non stai attento.

Prima di tutto, penso che sia il modo più conciso in cui è possibile verificare quella particolare condizione.

In secondo luogo, per me questo è un odore di codice che indica un potenziale difetto nel tuo design. Generalmente zero e zero non dovrebbero significare la stessa cosa. Se possibile, dovresti provare a eliminare la possibilità che val sia zero prima di premere questo codice, controllandolo all'inizio del metodo o in qualche altro meccanismo.

Potresti avere un motivo perfettamente legittimo per farlo, nel qual caso penso che il tuo codice sia buono, ma almeno prenderei in considerazione l'idea di provare a sbarazzarmi del controllo zero, se possibile.

Da Ruby 2.3.0 in poi, è possibile combinare l'operatore di navigazione sicura ( & amp ;. ) con Numero # diverso da zero? . & amp ;. restituisce zero se l'istanza era zero e diverso da zero? - se il numero era 0 :

unless val&.nonzero?
  # Is nil or zero
end

O postfisso:

do_something unless val&.nonzero?

Puoi usare Object.nil? per testare lo zero in modo specifico (e non farsi prendere tra false e zero). Puoi anche applicare una patch di scimmia a un metodo in Object.

class Object
   def nil_or_zero?
     return (self.nil? or self == 0)
   end
end

my_object = MyClass.new
my_object.nil_or_zero?
==> false

Questo non è raccomandato poiché le modifiche all'oggetto sono difficili da tracciare per i colleghi e possono rendere imprevedibile il tuo codice per gli altri.

Credo che il tuo codice sia errato; testerà infatti tre valori: nil , false e zero. Questo perché l'espressione ! Val è vera per tutti i valori falsi, che in Ruby è zero e false .

Il meglio che posso inventare adesso è

if val == nil || val == 0
  # do stuff
end

Che ovviamente non è molto intelligente, ma (molto) chiaro.

nil.to_i restituisce zero, quindi spesso faccio questo:

val.to_i.zero?

Tuttavia, otterrai un'eccezione se val è mai un oggetto che non risponde_ a #to_i.

La mia soluzione usa anche i perfezionamenti, meno i condizionali.

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if val.nothing?
  # Do something
end

Rails lo fa tramite metodi di query degli attributi, dove oltre a false e zero, 0 e " " valuta anche come falso.

if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation

Tuttavia ha la sua quota di detrattori. http://www.joegrossberg.com/archives/002995.html

Per essere il più idiomatico possibile, suggerirei questo.

if val.nil? or val == 0
    # Do something
end

A causa:

  • Usa lo zero? metodo.
  • Utilizza " o " operatore, che è preferibile a ||.
  • Non utilizza parentesi, che in questo caso non sono necessarie. Le parentesi devono essere utilizzate solo quando hanno qualche scopo, come ad esempio la precedenza di alcuni operatori.

Il modo più breve e migliore dovrebbe essere

if val&.>(0)
  # do something
end

Per val & amp;. > (0) restituisce zero quando val è zero poiché > fondamentalmente è anche un metodo, zero uguale a falso in rubino. Restituisce falso quando val == 0 .

Breve e chiaro

[0, nil] .include? (val)

Mi occupo di questo definendo un " is? " metodo, che posso quindi implementare in modo diverso su varie classi. Quindi per Array, "è?" significa "dimensione > 0"; per Fixnum significa " self! = 0 " ;; per String significa " self! = '' " ;. NilClass, ovviamente, definisce "è?" come solo tornare a zero.

Puoi usare case se ti piace:

 case val with nil, 0
      # do stuff
 end

Quindi puoi usare tutto ciò che funziona con === , il che è bello a volte. O fai qualcosa del genere:

not_valid = nil, 0
case val1 with *not_valid
      # do stuff
 end
 #do other stuff
 case val2 with *not_valid, false    #Test for values that is nil, 0 or false
      # do other other stuff
 end

Non è esattamente un buon OOP, ma è molto flessibile e funziona. Il mio if di solito finisce comunque come case .

Ovviamente Enum.any? / Enum.include? funziona anche in qualche modo ... se ti piace diventare davvero enigmatico:

if [0, nil].include? val
    #do stuff
end

La cosa giusta da fare è ovviamente definire un metodo o una funzione. Oppure, se devi fare la stessa cosa con molti valori, usa una combinazione di quei simpatici iteratori.

Mi piace molto il metodo Rails vuoto? per quel tipo di cose, ma non restituirà true per 0 . Quindi puoi aggiungere il tuo metodo:

def nil_zero? 
  if respond_to?(:zero?) 
    zero? 
  else 
    !self 
  end 
end 

E controllerà se un valore è zero o 0:

nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false

if val.nil_zero?
  #...
end

Invece di rattoppare le scimmie in una classe, potresti usare perfezionamenti a partire da Ruby 2.1. I perfezionamenti sono simili al patching delle scimmie; in ciò, ti consentono di modificare la classe, ma la modifica è limitata all'ambito in cui desideri utilizzarla.

Questo è eccessivo se vuoi fare questo controllo una volta, ma se ti stai ripetendo è un'ottima alternativa al patching delle scimmie.

module NilOrZero
  refine Object do
    def nil_or_zero?
      nil? or zero?
    end
  end
end

using NilOrZero
class Car
  def initialize(speed: 100)
    puts speed.nil_or_zero?
  end
end

car = Car.new              # false
car = Car.new(speed: nil)  # true
car = Car.new(speed: 0)    # true

I perfezionamenti sono stati modificati nell'ultimo minuto per essere inclusi nel file. Quindi esempi precedenti potrebbero averlo dimostrato, il che non funzionerà.

class Car
  using NilOrZero
end

Questo è molto conciso:

if (val || 0) == 0
  # Is nil, false, or zero.
end

Funziona finché non ti dispiace trattare false come nil . Nei progetti a cui ho lavorato, questa distinzione conta solo una volta ogni tanto. Il resto del tempo preferisco personalmente saltare .nil? e avere un codice leggermente più breve.

[ Aggiorna : non scrivo più questo genere di cose. Funziona ma è troppo criptico. Ho cercato di correggere i miei misfatti cambiando i pochi posti in cui l'ho fatto.]

A proposito, non ho usato .zero? poiché questo solleva un'eccezione se val è, diciamo, una stringa. Ma .zero? andrebbe bene se sai che non è così.

Questo valore è true per zero e zero: nil.to_s.to_d == 0

unless (val || 0).zero?

    # do stufff

end

Un'altra soluzione:

if val.to_i == 0
  # do stuff
end
val ||= 0
if val == 0
# do something here
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top