Я ищу краткий способ проверить значение, чтобы узнать, равно ли оно нулю или нулю. Сейчас я делаю что-то вроде:
if (!val || val == 0)
# Is nil or zero
end
Но это кажется очень неуклюжим.
Ответы:
У объектов ноль? метод .
if val.nil? || val == 0
[do something]
end
Или всего по одной инструкции:
[do something] if val.nil? || val == 0
or
не требует здесь скобок и будет совершенно естественно прочитан опытным рубистом. Единственные люди, которых когда-либо укусили ||
против, or
- это люди, которые никогда не программировали Perl :)
val && val == 0
лучше.
Если вам действительно нравятся названия методов с вопросительными знаками в конце:
if val.nil? || val.zero?
# do stuff
end
Ваше решение в порядке, как и некоторые другие решения.
Ruby может заставить вас искать красивый способ сделать все, если вы не будете осторожны.
Начиная с Ruby 2.3.0, вы можете комбинировать безопасный оператор навигации ( &.
) с Numeric#nonzero?
. &.
возвращает, nil
если экземпляр был nil
и nonzero?
- если номер был 0
:
unless val&.nonzero?
# Is nil or zero
end
Или постфикс:
do_something unless val&.nonzero?
unless val&.nonzero?
переводится как «если val равно нулю или нулю»
do_something if val&.nonzero?
(иначе, если val
нет nil
и не ноль).
Во-первых, я думаю, что это наиболее краткий способ проверить это конкретное состояние.
Во-вторых, для меня это запах кода, который указывает на потенциальную ошибку в вашем дизайне. Обычно ноль и ноль не должны означать одно и то же. Если возможно, вам следует попытаться исключить возможность того, что val будет равно нулю, прежде чем вы нажмете этот код, либо проверив это в начале метода, либо каким-либо другим механизмом.
У вас может быть вполне законная причина для этого, и в этом случае я думаю, что ваш код хорош, но я бы по крайней мере подумал о том, чтобы попытаться избавиться от проверки nil, если это возможно.
Вы можете использовать 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
Это не рекомендуется, поскольку коллегам сложно отслеживать изменения в Object, и это может сделать ваш код непредсказуемым для других.
nil?
всегда вернет false. nil?
возвращает true только для NilClass.
Object
, NilClass
и Numeric
. Object
вернется false
, NilClass
вернется true
и Numeric
вернется zero?
.
nil.to_i возвращает ноль, поэтому я часто делаю это:
val.to_i.zero?
Однако вы получите исключение, если val когда-либо является объектом, который не отвечает_to #to_i.
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
Я считаю, что ваш код неверен; это будет на самом деле тест для трех значений: nil
, false
и ноль. Это потому, что !val
выражение истинно для всех ложных значений, которыми в Ruby является nil
и false
.
Лучшее, что я могу придумать прямо сейчас, это
if val == nil || val == 0
# do stuff
end
Что конечно не очень умно, но (очень) понятно.
В моем решении также используются уточнения без условных выражений.
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 делает это с помощью методов запроса атрибутов, где в дополнение к 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
#attribute
, потому что я не могу найти ничего подобного.
Чтобы быть как можно более идиоматичным, я предлагаю следующее.
if val.nil? or val == 0
# Do something
end
Потому как:
Коротко и ясно
[0, nil].include?(val)
val.in? [0,nil]
Самый короткий и лучший способ должен быть
if val&.>(0)
# do something
end
Ибо val&.>(0)
он возвращает nil, когда val равно nil, поскольку> в основном также является методом, nil равно false в ruby. Он возвращает false, когда val == 0
.
Я имею дело с этим, определяя "есть?" метод, который я затем могу реализовать по-разному для разных классов. Итак, для массива "есть?" означает «размер> 0»; для Fixnum это означает «self! = 0»; для String это означает «self! = ''». NilClass, конечно же, определяет "есть?" как просто возвращение ноль.
Вы можете использовать, 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
s в case
любом случае обычно заканчиваются как s.
Конечно Enum.any?
/ Enum.include?
вид тоже работает ... если вам нравится быть действительно загадочным:
if [0, nil].include? val
#do stuff
end
Правильно, конечно, определить метод или функцию. Или, если вам нужно проделать то же самое со многими значениями, используйте комбинацию этих хороших итераторов.
Я на самом деле , как Rails blank?
метод для такого рода вещей, но он не будет возвращаться true
к 0
. Итак, вы можете добавить свой метод:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
И он проверит, является ли какое-то значение нулем или 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Вместо того, чтобы обезьяны исправлять класс, вы можете использовать улучшения, начиная с 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
Это очень кратко:
if (val || 0) == 0
# Is nil, false, or zero.
end
Это работает до тех пор, пока вы не против обращаться false
с тем же, что и nil
. В проектах, над которыми я работал, это различие имеет значение лишь изредка. В остальное время я предпочитаю пропускать .nil?
и иметь немного более короткий код.
[ Обновление : я больше не пишу такие вещи. Это работает, но слишком загадочно. Я пытался исправить свои проступки, изменив несколько мест, где я это сделал.]
Кстати, я не использовал, .zero?
так как это вызывает исключение, если val
, скажем, строка. Но .zero?
было бы хорошо, если бы вы знали, что это не так.
[edited]
Я думал, что если бы val
было nil, то это выражение оценило бы nil == 0
(и, таким образом, вернет false
). Однако, похоже, он действительно работает, хотя я не думаю, что он очень удобочитаемый.
Другое решение:
if val.to_i == 0
# do stuff
end
"5".to_i == 5
, но ты более-менее прав. Умно, но на самом деле не работает.
val ||= 0
if val == 0
# do something here
end
val
нужно сохранить? Вы сбиваете входные данные с помощью этого метода, и есть более эффективные и менее разрушительные способы проверки на ноль или ноль.
false
?