Question

Je cherche un moyen concis de vérifier une valeur pour savoir si elle est nulle ou nulle. Actuellement, je fais quelque chose comme:

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

Mais cela semble très maladroit.

Était-ce utile?

La solution

Les objets ont un nil? méthode .

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

Ou, pour une seule instruction:

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

Autres conseils

Si vous aimez vraiment les noms de méthodes avec des points d'interrogation à la fin:


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

Votre solution est satisfaisante, de même que quelques-unes des autres solutions.

Ruby peut vous aider à faire tout ce que vous voulez, si vous ne faites pas attention.

Tout d’abord, je pense que c’est à peu près la façon la plus concise de vérifier cette condition particulière.

Deuxièmement, c’est une odeur de code qui indique une faille potentielle dans votre conception. Généralement, zéro et zéro ne devraient pas signifier la même chose. Si possible, essayez d’éliminer la possibilité que val soit nul avant de frapper ce code, en vérifiant cela au début de la méthode ou par un autre mécanisme.

Vous avez peut-être une raison tout à fait légitime de le faire, auquel cas je pense que votre code est bon, mais au moins, je penserais à essayer de supprimer le chèque nul si possible.

À partir de Ruby 2.3.0, vous pouvez associer l'opérateur de navigation sécurisée ( & amp;. ) à Numérique # non nul? . & amp;. renvoie nil si l'instance était nil et non nul? - si le nombre était 0 :

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

Ou postfixe:

do_something unless val&.nonzero?

Vous pouvez utiliser Object.nil? tester spécifiquement pour zéro (et ne pas se laisser prendre entre faux et zéro). Vous pouvez aussi monkey-patcher une méthode dans 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

Cela n'est pas recommandé car il est difficile pour les collègues de suivre les modifications apportées à Object et peut rendre votre code imprévisible pour les autres.

Je pense que votre code est incorrect. il testera en fait trois valeurs: nil , false et zéro. En effet, l'expression ! Val est vraie pour toutes les valeurs fausses, lesquelles dans Ruby sont nil et false .

Le mieux que je puisse trouver en ce moment est

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

Ce qui, bien sûr, n’est pas très intelligent, mais très clair.

nil.to_i renvoie zéro, je le fais souvent ainsi:

val.to_i.zero?

Cependant, vous obtiendrez une exception si val est un objet qui ne répond pas_à #to_i.

Ma solution utilise également les raffinements, moins les conditions.

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 le fait via des méthodes de requête attributaires, où en plus de false et nil, 0 et """ évaluer aussi à faux.

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

Cependant, il a sa part de détracteurs. http://www.joegrossberg.com/archives/002995.html

Pour être aussi idiomatique que possible, je suggérerais ceci.

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

Parce que:

  • Il utilise le zéro? méthode.
  • Il utilise les options " ou " opérateur, ce qui est préférable à ||.
  • Il n'utilise pas de parenthèses, ce qui n'est pas nécessaire dans ce cas. Les parenthèses ne doivent être utilisées que lorsqu'elles servent à quelque chose, par exemple, remplacer la priorité de certains opérateurs.

Le moyen le plus court et le meilleur devrait être

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

Pour , val & amp;. > (0) il ne retourne rien lorsque val est nul puisque > est fondamentalement aussi une méthode, nulle égale à false en rubis. Il renvoie false lorsque val == 0 .

Court et clair

[0, nil] .include? (val)

Je résous ce problème en définissant un "est?" méthode, que je peux ensuite mettre en œuvre différemment sur différentes classes. Donc pour Array, "is?" signifie "taille > 0"; pour Fixnum, cela signifie "self! = 0"; pour String, cela signifie "self! = ''". NilClass, bien sûr, définit "is". comme revenant à zéro.

Vous pouvez utiliser case si vous aimez:

 case val with nil, 0
      # do stuff
 end

Ensuite, vous pouvez utiliser tout ce qui fonctionne avec === , ce qui est bien parfois. Ou faire quelque chose comme ça:

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

Ce n’est pas vraiment une bonne POO, mais c’est très flexible et ça marche. Mes if se retrouvent généralement sous la forme .

Bien sûr, Enum.any? / Enum.include? fonctionne aussi ... si vous voulez être vraiment crypté:

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

La bonne chose à faire est bien sûr de définir une méthode ou une fonction. Ou, si vous devez faire la même chose avec beaucoup de valeurs, utilisez une combinaison de ces bons itérateurs.

J'aime beaucoup la méthode Rails blank? pour ce genre de choses, mais elle ne renverra pas true pour 0 . Vous pouvez donc ajouter votre méthode:

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

Et il vérifiera si une valeur est nulle ou 0:

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

if val.nil_zero?
  #...
end

Au lieu de patcher une classe, vous pourriez utiliser améliorations à partir de Ruby 2.1. Les raffinements sont similaires à la correction de singe; en cela, ils vous permettent de modifier la classe, mais la modification est limitée à la portée dans laquelle vous souhaitez l'utiliser.

C’est excessif si vous voulez effectuer cette vérification une fois, mais si vous vous répétez, c’est une excellente alternative au patchage des singes.

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
Les

modifications ont été modifiées à la dernière minute pour être intégrées au fichier. Ainsi, des exemples précédents peuvent avoir montré cela, ce qui ne fonctionnera pas.

class Car
  using NilOrZero
end

C’est très concis:

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

Cela fonctionne tant que cela ne vous dérange pas de traiter false de la même manière que nil . Dans les projets sur lesquels j'ai travaillé, cette distinction n'a d'importance que de temps en temps. Le reste du temps, je préfère personnellement ignorer .nil? et obtenir un code légèrement plus court.

[ Mettre à jour : je n'écris plus ce genre de chose. Cela fonctionne mais est trop cryptique. J'ai essayé de corriger mes méfaits en changeant les quelques endroits où je les ai faits.]

En passant, je n'ai pas utilisé .zero? , car cela soulève une exception si val est, par exemple, une chaîne. Mais .zero? conviendrait si vous savez que ce n'est pas le cas.

Ceci vaut true pour nil et zéro: nil.to_s.to_d == 0

unless (val || 0).zero?

    # do stufff

end

Une autre solution:

if val.to_i == 0
  # do stuff
end
val ||= 0
if val == 0
# do something here
end
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top