Estoy buscando una forma concisa de verificar un valor para ver si es nulo o cero. Actualmente estoy haciendo algo como:Mejor expresión de ruby para "cero o cero"
if (!val || val == 0)
# Is nil or zero
end
Pero esto parece muy torpe.
Estoy buscando una forma concisa de verificar un valor para ver si es nulo o cero. Actualmente estoy haciendo algo como:Mejor expresión de ruby para "cero o cero"
if (!val || val == 0)
# Is nil or zero
end
Pero esto parece muy torpe.
Los objetos tienen un nil? method.
if val.nil? || val == 0
[do something]
end
O, para una sola instrucción:
[do something] if val.nil? || val == 0
tenga cuidado con el uso de "o" y "y", por cierto, tienen una precedencia diferente y muy baja comparado con || y &&. Ver http: //blog.jayfields.com/2007/08/ruby-operator-precedence-of-and-which.html para algunas observaciones. –
Estoy de acuerdo con un póster del "olor" en la pregunta, sin embargo, para mí esto es más de la manera ruby. – Jonke
La precedencia de 'o' no requiere paréntesis aquí, y se leerá con total naturalidad a un Rubyista experimentado. Las únicas personas que son mordidas por '||' contra 'o' son personas que nunca han programado Perl :) – ephemient
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 puedo llegar a este momento es
if val == nil || val == 0
# do stuff
end
que por supuesto no es muy inteligente, pero (muy) clara.
probablemente pueda suponer que la variable en cuestión es numérica. Si ni siquiera sabe si es un Booleano o un Numérico, hay problemas mayores en el código. –
Yo usaría .nil? not == nil – RichH
En primer lugar, creo que es la forma más concisa en la que puede verificar esa condición en particular.
En segundo lugar, para mí este es un olor a código que indica un posible defecto en su diseño. En general, cero y cero no deberían significar lo mismo. Si es posible, debe intentar eliminar la posibilidad de que val sea nulo antes de presionar este código, ya sea verificándolo al comienzo del método o mediante algún otro mecanismo.
Es posible que tenga una razón perfectamente legítima para hacerlo, en cuyo caso creo que su código es bueno, pero al menos consideraría tratar de deshacerse de la comprobación nula si es posible.
¡Muy correcto sobre el olor del código! +1 Podría considerar buscar en el patrón NullObject http://en.wikipedia.org/wiki/Null_Object_pattern – abyx
Puede usar Object.nil? para probar nulo específicamente (y no quedar atrapado entre falso y nulo). También puedes aplicar un parche a un método en Objeto.
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 es recomendable ya que los cambios de objeto son difíciles para los compañeros de trabajo para rastrear, y puede hacer que el código impredecible a otros.
Me gustaría modificar la clase numérica en lugar de Object. – epochwolf
epochwolf, si pones esto en la clase Numérica, ¿'nil?' Siempre devolverá falso. 'nil?' solo devuelve verdadero en NilClass. –
Puede implementar el método en 'Object',' NilClass' y 'Numeric'. 'Object' devolvería' false', 'NilClass' devolvería' true' y 'Numeric' devolvería' zero? '. – Stefan
Rails hace esto a través de métodos de consulta de atributos, donde además de falso y nulo, 0 y "" también evalúan 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
El enlace no funciona. Tengo curiosidad sobre el método '# attribute', porque no puedo encontrar nada de eso. – mrzasa
Es algo que Rails/ActiveRecord agrega sobre la marcha. Si el cliente tiene un campo de nombre, ¿nombre? se agrega automáticamente para verificar si el nombre está en blanco o nulo. Consulte http://api.rubyonrails.org/classes/ActiveRecord/Base.html - busque la sección 'métodos de consulta de atributos' – Gishu
me encargo de esto mediante la definición de un "es?" método, que luego puedo implementar de manera diferente en varias clases. Entonces para Array, "¿es?" significa "tamaño> 0"; para Fixnum significa "self! = 0"; para String significa "self! = ''". NilClass, por supuesto, define "¿es?" simplemente devolviendo nil.
Para ser lo más idiomático posible, sugeriría esto.
if val.nil? or val == 0
# Do something
end
Porque:
Aunque sé que esto es literalmente hace 7 años, he votado negativamente debido a esto: https://github.com/bbatsov/ruby-style-guide#no-and-or-or –
val ||= 0
if val == 0
# do something here
end
-1: ¿Qué pasa si el valor en 'val' necesita ser guardado? Está destruyendo los datos de entrada con este método, y existen formas mejores y menos destructivas de verificar cero o cero. –
¿Qué tal if (val || 0) .zero? – timkay
Si realmente te gusta nombres de los métodos con los signos de interrogación al final:
if val.nil? || val.zero?
# do stuff
end
Su solución está muy bien, al igual que algunas de las otras soluciones.
Ruby puede hacer que busques una forma bonita de hacer todo, si no tienes cuidado.
Puede utilizar case
si te gusta:
case val with nil, 0
# do stuff
end
continuación, puede utilizar cualquier cosa que funcione con ===
, que es agradable 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 bueno OOP, pero es muy flexible y funciona. Mi if
s generalmente termina como case
s de todos modos.
Por supuesto Enum.any?
/Enum.include?
tipo de trabajos también ... si se quiere conseguir realmente críptico:
if [0, nil].include? val
#do stuff
end
Lo que hay que hacer es, por supuesto, para definir un método o función. O bien, si tiene que hacer lo mismo con muchos valores, use una combinación de esos simpáticos iteradores.
Otra solución:
if val.to_i == 0
# do stuff
end
Esto solo funciona si val es un entero o nulo; 0.5.to_i == 0, any_string.to_i == 0, etc. –
'" 5 ".to_i == 5', pero está más o menos en lo cierto. Inteligente pero en realidad no funciona. –
nil.to_i devuelve cero, así que a menudo hago esto:
val.to_i.zero?
Sin embargo, obtendrá una excepción si val es siempre un objeto que no hace respond_to #to_i.
-1 por la misma razón que la respuesta de Scott no funciona. –
Me gusta mucho el método Rails blank?
para ese tipo de cosas, pero no devolverá true
para 0
. Así que usted puede añadir su método:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
y va a comprobar si un valor es nulo o 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Esto es muy concisa:
if (val || 0) == 0
# Is nil, false, or zero.
end
Funciona siempre y cuando no le importa tratar false
lo mismo 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 ligeramente más corto.
[Actualización: Ya no escribo este tipo de cosas.Funciona, pero es demasiado críptico. He intentado corregir mis fechorías cambiando los pocos lugares donde lo hice.]
Por cierto, no usé .zero?
ya que esto genera una excepción si val
es, por ejemplo, una cadena. Pero .zero?
estaría bien si sabes que no es el caso.
'[editado]' Pensé que si 'val' era nil, entonces esta expresión se evaluaría como' nil == 0' (y, por lo tanto, devolvería 'false'). Sin embargo, parece que realmente funciona, aunque no creo que sea muy legible. – omnikron
Ahora creo que mi enfoque aquí fue demasiado críptico, solo para guardar unos pocos caracteres, y no lo escribiría así hoy en día. Así que no espero ningún voto positivo, pero estoy un poco sorprendido por los votos a favor de una respuesta que funciona (aunque era de dudoso gusto) ... – antinome
En lugar de mono parchear una clase, you could use refinements a partir de Ruby 2.1. Los refinamientos son similares a los parches de mono; en eso, le permiten modificar la clase, pero la modificación se limita al ámbito en el que desea usarla.
Esto es exagerado si desea hacer este control una vez, pero si se repite usted mismo es gran 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
Refinements were changed en el último minuto para estar en el ámbito en el fichero. Así que los ejemplos anteriores pueden haber demostrado esto, lo cual no funcionará.
class Car
using NilOrZero
end
De Rubí 2.3.0 en adelante, se puede combinar el operador navegación segura (&.
) con Numeric#nonzero?
. &.
vuelve nil
si la instancia fue nil
y nonzero?
- si el número era 0
:
unless val&.nonzero?
# Is nil or zero
end
O postfijos:
do_something unless val&.nonzero?
Esta fue una excelente respuesta nueva y moderna. Además, hay un excelente artículo sobre por qué usarlo aquí: [The Safe Navigation Operator (&.) En Ruby] (http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/) –
Muy conciso, pero sin el comentario me llevaría un momento entender que 'a menos que val & .nonzero?' Se traduzca a "si val es nulo o cero" – Stefan
@Stefan, de acuerdo. Yo no usaría esto en el código de producción yo mismo. Lo incluí para completar el proceso. Sin embargo, lo opuesto es perfectamente legible: 'do_something if val & .nonzero?' (También conocido como 'val' no es 'nil' y no es cero). – ndn
más cortos y mejor manera debe ser
if val&.>(0)
# do something
end
Para val&.>(0)
devuelve nil cuando val es nulo puesto> básicamente es también un método, nada igual a falsa en rubí. Devuelve falso cuando val == 0
.
¿El más corto sobre qué ?, ¿la mejor manera que qué? –
Este resultado verdadero de cero y cero: nil.to_s.to_d == 0
lo que debería suceder si val es igual a 'false'? –