Pregunta

Estoy buscando una forma concisa de verificar un valor para ver si es nulo o cero. Actualmente estoy haciendo algo como:

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

Pero esto parece muy torpe.

¿Fue útil?

Solución

Los objetos tienen un nulo? método .

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

O, para una sola instrucción:

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

Otros consejos

Si realmente le gustan los nombres de métodos con signos de interrogación al final:


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

Su solución está bien, al igual que algunas de las otras soluciones.

Ruby puede hacer que busques una manera bonita de hacerlo todo, si no tienes cuidado.

En primer lugar, creo que esa es la forma más concisa en la que puedes verificar esa condición en particular.

En segundo lugar, para mí este es un código de olor que indica una falla potencial en su diseño. Generalmente cero y cero no deberían significar lo mismo. Si es posible, debe intentar eliminar la posibilidad de que val sea nulo antes de ingresar a este código, ya sea al verificar el principio del método o algún otro mecanismo.

Es posible que tenga una razón perfectamente legítima para hacer esto, en cuyo caso creo que su código es bueno, pero al menos consideraría intentar deshacerme del cheque nulo si es posible.

A partir de Ruby 2.3.0, puede combinar el operador de navegación segura ( & amp ;. ) con Numérico # ¿no es cero? . & amp ;. devuelve nil si la instancia era nil y no cero? - si el número era 0 :

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

O postfix:

do_something unless val&.nonzero?

¿Puedes usar Object.nil? para probar nulo específicamente (y no quedar atrapado entre falso y nulo). También puedes parchear un método en 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

Esto no se recomienda ya que los cambios en Objeto son difíciles de rastrear para los compañeros de trabajo y pueden hacer que su código sea impredecible para otros.

Creo que su código es incorrecto; de hecho, probará tres valores: nil , false y cero. Esto se debe a que la expresión ! Val es verdadera para todos los valores que son falsos, que en Ruby es nil y false .

Lo mejor que se me ocurre ahora mismo es

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

Lo que, por supuesto, no es muy inteligente, pero (muy) claro.

nil.to_i devuelve cero, así que a menudo hago esto:

val.to_i.zero?

Sin embargo, obtendrá una excepción si val es un objeto que no responde_a #to_i.

Mi solución también usa Refinamientos, menos los condicionales.

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 hace esto a través de métodos de consulta de atributos, donde además de falso y nulo, 0 y " " También evaluar a falso.

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

Sin embargo, tiene su cuota de detractores. http://www.joegrossberg.com/archives/002995.html

Para ser lo más idiomático posible, sugeriría esto.

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

Porque:

  • Utiliza el nil? método.
  • Utiliza el "o" operador, que es preferible a ||.
  • No utiliza paréntesis, que no son necesarios en este caso. Los paréntesis solo deben usarse cuando tienen algún propósito, como anular la prioridad de ciertos operadores.

La forma más corta y mejor debería ser

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

Para val & amp;. > (0) devuelve nulo cuando val es nulo ya que > Básicamente es también un método, nil igual a falso en ruby. Devuelve false cuando val == 0 .

Corto y claro

[0, nil] .include? (val)

Me ocupo de esto definiendo un " es? " Método, que luego puedo implementar de manera diferente en varias clases. Así que para Array, " es? & Quot; significa " tamaño > 0 " ;; para Fixnum significa "self! = 0"; para String significa "yo mismo" = "'" ;. NilClass, por supuesto, define " es? & Quot; como simplemente regresando nulo.

Puede usar case si lo desea:

 case val with nil, 0
      # do stuff
 end

Entonces puedes usar cualquier cosa que funcione con === , lo cual es bueno a veces. O haga algo como esto:

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

No es exactamente una buena OOP, pero es muy flexible y funciona. Mis if s generalmente terminan como case s de todos modos.

Por supuesto, Enum.any? / Enum.include? también funciona ... si desea ser realmente críptico:

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

Lo correcto es, por supuesto, definir un método o función. O, si tiene que hacer lo mismo con muchos valores, use una combinación de esos buenos iteradores.

Me gusta mucho el método en blanco? de Rails para ese tipo de cosas, pero no devolverá true para 0 . Para que puedas agregar tu método:

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

Y comprobará si algún valor es nulo o 0:

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

if val.nil_zero?
  #...
end

En lugar de parchar parches en una clase, puede usar refinamientos comenzando en Ruby 2.1. Los refinamientos son similares a los parches de monos; en eso, le permiten modificar la clase, pero la modificación se limita al alcance en el que desea usarla.

Esto es una exageración si quieres hacer esta comprobación una vez, pero si te estás repitiendo, es una excelente alternativa al parche de monos.

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

Las modificaciones se modificaron en el último minuto para que el alcance del archivo. Así que los ejemplos anteriores pueden haber mostrado esto, lo cual no funcionará.

class Car
  using NilOrZero
end

Esto es muy conciso:

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

Funciona siempre y cuando no te importe tratar a false de la misma manera que nil . En los proyectos en los que he trabajado, esa distinción solo importa de vez en cuando. El resto del tiempo personalmente prefiero omitir .nil? y tener un código un poco más corto.

[ Actualización : Ya no escribo este tipo de cosas. Funciona pero es demasiado críptico. He tratado de corregir mis faltas cambiando los pocos lugares donde lo hice.]

Por cierto, no utilicé .zero? ya que esto genera una excepción si val es, por ejemplo, una cadena. Pero .zero? estaría bien si sabes que ese no es el caso.

Esto se evalúa como verdadero para nil y cero: nil.to_s.to_d == 0

unless (val || 0).zero?

    # do stufff

end

Otra solución:

if val.to_i == 0
  # do stuff
end
val ||= 0
if val == 0
# do something here
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top