Лучшая рубиновая идиома для "ноль или ноль"

Я ищу краткий способ проверить значение, чтобы узнать, равен ли он нулю или нулю. В настоящее время я делаю что-то вроде:

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

Но это кажется очень неуклюжим.

Ответ 1

Объекты имеют nil? Метод.

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

Или для одной инструкции:

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

Ответ 2

Если вам действительно нравятся имена методов с вопросительными знаками в конце:


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

Ваше решение в порядке, как и некоторые другие решения.

Ruby может заставить вас искать прекрасный способ сделать все, если вы не будете осторожны.

Ответ 3

Во-первых, я думаю, что о наиболее сжатом способе вы можете проверить это конкретное условие.

Во-вторых, для меня это запах кода, который указывает на потенциальный недостаток вашего дизайна. Как правило, ноль и ноль не должны означать одно и то же. Если возможно, вы должны попытаться исключить возможность того, что val будет равен нулю, прежде чем вы нажмете этот код, либо проверив это в начале метода, либо какой-либо другой механизм.

У вас может быть вполне законная причина сделать это, и в этом случае я думаю, что ваш код хорош, но я бы хотя бы подумал о попытке избавиться от проверки nil, если это возможно.

Ответ 4

Начиная с Ruby 2.3.0, вы можете объединить безопасный навигационный оператор (&.) с Numeric#nonzero?. &. возвращает nil, если экземпляр был nil и nonzero? - если число было 0:

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

Или постфикс:

do_something unless val&.nonzero?

Ответ 5

Вы можете использовать Object.nil? для проверки нулевого значения (и не попадания между ложными и нулевыми значениями). Вы также можете обезвредить метод в 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

Это не рекомендуется, так как изменения в объекте сложно отслеживать коллегам и могут сделать ваш код непредсказуемым для других.

Ответ 6

nil.to_i возвращает ноль, поэтому я часто делаю это:

val.to_i.zero?

Однако вы получите исключение, если val всегда является объектом, который не отвечает_to #to_i.

Ответ 7

Я считаю, что ваш код неверен; он фактически проверяет три значения: nil, false и ноль. Это происходит потому, что выражение !val истинно для всех значений, которые являются ложными, что в Ruby составляет nil и false.

Лучшее, что я могу придумать прямо сейчас, это

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

Что, конечно, не очень умно, но (очень) понятно.

Ответ 8

Мое решение также использовать уточнения, минус условные.

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

Ответ 9

Rails делает это с помощью методов запросов атрибутов, где помимо false и nil, 0 и "" также вычисляются как false.

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

Однако у него есть доля недоброжелателей. http://www.joegrossberg.com/archives/002995.html

Ответ 10

Чтобы быть как можно более идиоматичным, я бы предложил это.

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

Потому что:

  • Он использует нуль? Метод.
  • Он использует оператор "или", который предпочтительнее ||.
  • Он не использует круглые скобки, которые в этом случае не нужны. Скобки должны использоваться только тогда, когда они служат какой-то цели, например, переопределяют приоритет определенных операторов.

Ответ 11

Самый короткий и лучший способ должен быть

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

Для val&.>(0) он возвращает nil, когда val равен nil, поскольку> в основном также является методом, равным false в ruby. Возвращается false, когда val == 0.

Ответ 12

Короткие и четкие

[0, nil].include?(val)

Ответ 13

Я занимаюсь этим, определяя "есть?" . метод, который затем я могу реализовать по-разному на разных классах. Итак, для Маре, "есть?" означает "размеp > 0"; для Fixnum это означает "self!= 0"; для String это означает "self! =". NilClass, конечно, определяет "есть?" как только возвращающ ноль.

Ответ 14

Я только что удалил свой предыдущий ответ. Я неправильно понял вас и рекомендовал использовать метод #blank?.

В любом случае, я бы расширил класс Object и создал для этой цели метод.

Ответ 15

Вы можете использовать case, если хотите:

 case val with nil, 0
      # do stuff
 end

Затем вы можете использовать все, что работает с ===, что иногда бывает приятно. Или сделайте что-нибудь вроде этого:

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

Это не совсем хороший ООП, но он очень гибкий и работает. Мой if обычно заканчивается как case.

Конечно, Enum.any?/Enum.include? тоже работает... если вам нравится быть загадочным:

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

Правильная вещь - это, конечно, определить метод или функцию. Или, если вам нужно сделать то же самое со многими значениями, используйте комбинацию этих хороших итераторов.

Ответ 16

Мне действительно нравится метод Rails blank? для такого рода вещей, но он не вернет true для 0. Поэтому вы можете добавить свой метод:

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

И он будет проверять, является ли какое-либо значение равным nil или 0:

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

if val.nil_zero?
  #...
end

Ответ 17

Это очень краткий:

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

Он работает до тех пор, пока вы не против обрабатывать false так же, как nil. В проектах, над которыми я работал, это различие имеет значение только время от времени. В остальное время я лично предпочитаю пропускать .nil? и иметь несколько более короткий код.

[ Обновление: я больше ничего не пишу. Он работает, но слишком загадочен. Я попытался исправить свои проступки, изменив несколько мест, где я это сделал.]

Кстати, я не использовал .zero?, так как это вызывает исключение, если val есть, скажем, строка. Но .zero? будет в порядке, если вы знаете, что это не так.

Ответ 18

Вместо того, чтобы обезглавливать класс, вы можете использовать уточнения, начиная с Ruby 2.1. Уточнения подобны исправлениям обезьян; в этом случае они позволяют вам изменять класс, но модификация ограничивается областью, в которой вы хотите ее использовать.

Это слишком много, если вы хотите сделать эту проверку один раз, но если вы повторяете себя, это отличная альтернатива патчу обезьян.

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

Уточнения были изменены в последнюю минуту для привязки к файлу. Поэтому более ранние примеры могли показать это, что не сработает.

class Car
  using NilOrZero
end

Ответ 19

Это значение true для nil и zero: nil.to_s.to_d == 0

Ответ 20

unless (val || 0).zero?

    # do stufff

end

Ответ 21

Другое решение:

if val.to_i == 0
  # do stuff
end

Ответ 22

val ||= 0
if val == 0
# do something here
end