Pergunta

Eu estou procurando uma maneira concisa para verificar um valor para ver se ele é nulo ou zero. Atualmente estou fazendo algo como:

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

Mas isso parece muito desajeitado.

Foi útil?

Solução

Os objetos têm um nil? método .

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

Ou, para apenas uma instrução:

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

Outras dicas

Se você realmente gosta de nomes de métodos com pontos de interrogação no final:


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

A sua solução é bom, como são algumas das outras soluções.

Ruby pode fazer você procurar uma maneira bonita de fazer tudo, se você não tiver cuidado.

Em primeiro lugar eu acho que é sobre a maneira mais concisa você pode verificar para essa condição particular.

Em segundo lugar, para mim este é um cheiro de código que indica uma falha potencial em seu projeto. Geralmente zero e zero não deve significar a mesma coisa. Se possível, você deve tentar eliminar a possibilidade de val ser nil antes de bater este código, quer verificando que, no início do método ou algum outro mecanismo.

Você pode ter uma razão perfeitamente legítima para fazer isso nesse caso, eu acho que o código é bom, mas eu, pelo menos, considerar a tentar livrar-se do cheque nulo, se possível.

A partir de Ruby 2.3.0 em diante, você pode combinar o operador de navegação segura (&.) com Numeric#nonzero? . &. retornos nil se a instância foi nil e nonzero? - se o número foi 0:

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

Ou postfix:

do_something unless val&.nonzero?

Você pode usar o Object.nil? Para testar a nil especificamente (e não ficar preso entre falso e nil). Você pode macaco-patch um método para objetos bem.

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

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

Isto não é recomendado como alterações ao objeto são difíceis para os colegas de trabalho para rastrear e pode tornar seu código imprevisível para os outros.

Eu acredito que o código estiver incorreto; ele vai no teste de fato por três valores: nil, false , e zero. Isso ocorre porque a expressão !val é verdadeiro para todos os valores que são falsas, que em Ruby é nil e false.

O melhor que eu posso vir acima com agora é

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

Que, naturalmente, não é muito inteligente, mas (muito) clara.

retornos nil.to_i zero, por isso muitas vezes fazer isso:

val.to_i.zero?

No entanto, você receberá uma exceção se val é sempre um objeto que não faz respond_to #to_i.

A minha solução também usar refinamentos, menos os condicionais.

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 faz isso através de métodos de consulta de atributos, onde, além de false e nil, 0 e "" também avaliam como falsa.

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

No entanto, tem sua parcela de detratores. http://www.joegrossberg.com/archives/002995.html

Para ser tão idiomática quanto possível, eu sugiro isso.

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

Porque:

  • Ele usa o nulo? método.
  • Ele usa o operador "ou", que é preferível ||.
  • Não use parênteses, que não são necessários neste caso. Parênteses só deve ser usado quando eles servem para alguma coisa, como substituir a precedência de determinados operadores.

Shortest e melhor maneira deve ser

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

Para val&.>(0) ele retorna nulo quando val é nulo desde> basicamente é também um método, nada igual a falsa em ruby. Ele retornar falso quando val == 0.

curta e clara

[0, nil].include?(val)

Eu lido com isso definindo um "é?" método, que pode, então, implementar de forma diferente em várias classes. Assim, para Array, "é?" meios "size> 0"; para Fixnum que significa "auto = 0!"; para Cordas que significa "auto! = ''". NilClass, é claro, define "é?" como apenas retornando nil.

Você pode usar case se você gosta:

 case val with nil, 0
      # do stuff
 end

Em seguida, você pode usar qualquer coisa que funciona com ===, que é bom às vezes. Ou fazer algo parecido com isto:

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

Não é exatamente bom OOP, mas é muito flexível e ele funciona. Meus ifs geralmente acabam como cases de qualquer maneira.

É claro Enum.any? / tipo Enum.include? de obras também ... se você gosta de ficar muito enigmática:

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

A coisa certa a fazer é, naturalmente, para definir um método ou função. Ou, se você tem que fazer a mesma coisa com muitos valores, use uma combinação desses iterators agradáveis.

Eu realmente gosto Rails método blank? para esse tipo de coisas, mas não vai voltar true para 0. Então você pode adicionar o seu método:

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

E vai verificar se algum valor é nulo ou 0:

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

if val.nil_zero?
  #...
end

Em vez de macaco remendar uma classe, você poderia usar refinamentos começando no ruby ??2.1. Refinamentos são semelhantes aos patching macaco; em que, eles permitem que você modifique a classe, mas a modificação é limitada ao âmbito você deseja usá-lo em.

Este é um exagero se você quer fazer essa verificação uma vez, mas se você está repetindo-se que é uma ótima alternativa para patching macaco.

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

refinamentos foram alteradas no último minuto para ser delimitado para o arquivo. Então exemplos anteriores podem ter mostrado isso, que não vai funcionar.

class Car
  using NilOrZero
end

Isto é muito concisa:

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

Ele funciona, desde que você não se importa tratar false o mesmo que nil. Nos projetos em que já trabalhei, essa distinção só importa de vez em quando. O resto do tempo, eu, pessoalmente, prefiro ignorar .nil? e têm código ligeiramente mais curto.

[ Atualizar : eu não escrever este tipo de coisa mais. Ele funciona, mas é muito enigmática. Tentei definir certas meus erros, alterando os poucos lugares onde eu fiz isso.]

A propósito, eu não usar .zero? uma vez que este levanta uma exceção se val é, digamos, uma string. Mas .zero? seria bom se você sabe que não é o caso.

Isto avalia como verdadeira para zero e zero: nil.to_s.to_d == 0

unless (val || 0).zero?

    # do stufff

end

Outra solução:

if val.to_i == 0
  # do stuff
end
val ||= 0
if val == 0
# do something here
end
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top