Проверка, если переменная не ноль и не ноль в ruby

271

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

if(discount != nil && discount != 0) 
  ...
end

Есть лучший способ сделать это?

hectorsq
источник
1
Вероятно, потому что это точная копия stackoverflow.com/questions/209495/… .
Дэвид Нехм
1
Что делать, если discountложь?
Эндрю Гримм
1
Я думаю, discount.in? [0, nil]что более чистый способ возможен
intmarinoreturn0

Ответы:

428
разве что discount.nil? || скидка == 0
  # ...
конец
Деян Симич
источник
31
Используйте 'или' вместо ||
Орион Эдвардс
93
@ orion-edwards почему?
НАРКОЗ
39
Использование «или» опасно. 'or' имеет более низкий уровень присутствия операторов, чем '=', поэтому следующее имеет неожиданное поведение: a = false или true #a ложно после этого оператора
Tom G
20
@xiy в настоящее время руководство рекомендует делать вид или и и не существует (|| это или && и?)
user3125280
67
Текущие "Ruby Style Guide" стоит The and and or keywords are banned. It's just not worth it. Always use && and || instead.. И это правильно по причинам Дэвида и Тома.
Андре Фигейредо
40
class Object
  def nil_zero?
    self.nil? || self == 0
  end
end

# which lets you do
nil.nil_zero? # returns true
0.nil_zero?   # returns true
1.nil_zero?   # returns false
"a".nil_zero? # returns false

unless discount.nil_zero?
  # do stuff...
end

Остерегайтесь обычных заявлений об отказе от ответственности ... великой власти / ответственности, исправлений обезьян, ведущих на темную сторону и т. Д.

madlep
источник
28

хорошо, через 5 лет прошло ....

if discount.try :nonzero?
  ...
end

Важно отметить, что tryон определен в геме ActiveSupport, поэтому он недоступен в обычном ruby.

переписан
источник
7
Обратите внимание, что это специфичный для рельсов ответ. Ванильный рубин не имеет tryметода.
Том Лорд
Верный. Хотя это больше похоже на спецификацию ActiveSupport, которая намного легче и широко используется, чем полные рельсы. В любом случае, ответ @ ndn верный.
переписано
Отредактировано для использования безопасной навигации
переписано
1
Ответ теперь дублирует stackoverflow.com/a/34819818/1954610 ... Я думаю, что есть смысл оставить его так, tryчтобы показать альтернативный вариант (именно поэтому он был отклонен в первую очередь!), При условии, что это ясно для читатель, который ActiveSupportне ванильный рубин.
Том Лорд
Точка занята, ответ откатан.
переписано
27
если только [nil, 0] .include? (скидка) 
  # ...
конец
Деян Симич
источник
13
Прекрасный? Да. Удобочитаемый? На самом деле, нет.
Эль Ниндзя Трепадор
1
Я нахожу это прекрасно читаемым, и я бы предпочел его новому классу. Отлично сработано.
colincr
Наиболее рубиновый подход к обработке двух условий.
Югендран
23

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

if discount&.nonzero?
  # ...
end

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

do_something if discount&.nonzero?
ndnenkov
источник
"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Это не безопасно использовать на произвольных объектах.
Том Лорд
2
@TomLord, как указано в предыдущем комментарии, не предназначался для работы с произвольными объектами. Вместо этого это касается случая, когда у вас есть что-то, что вы знаете, должно быть числом, но также может быть nil.
ndnenkov
Я хотел бы прояснить этот факт в ответе, вместо того, чтобы кто-то прочитал это и не заметил отказ от комментариев в комментариях.
Том Лорд
@TomLord, это указано в ответе " nonzero?- если номер был 0" . Также необходимость проверять, возникает ли совершенно произвольный объект 0крайне редко по сравнению с тем, чтобы проверять число, которое может или не может быть nil. Следовательно, это почти подразумевается. Даже если кто-то делает противоположное предположение, он сразу же поймет, что происходит, когда попытается его выполнить.
ndnenkov
17
if (discount||0) != 0
  #...
end
Раймондс Симановскис
источник
Это мой любимый ответ
Уилсон Фрейтас
15

Вы могли бы сделать это:

if (!discount.nil? && !discount.zero?)

Здесь важен порядок, потому что если discountесть nil, то у него не будет zero?метода. Оценка Руби по короткому замыканию должна препятствовать тому, чтобы он пытался оценить discount.zero?, однако, если discountесть nil.

Джереми Рутен
источник
11

Вы можете преобразовать вашу пустую строку в целочисленное значение и проверить ноль ?.

"".to_i.zero? => true
nil.to_i.zero? => true
oivoodoo
источник
осторожно: 0.1.to_i == 0
Саймон Б.
3
if discount and discount != 0
  ..
end

обновить, это будет falseдляdiscount = false

rubyprince
источник
2

Вы можете воспользоваться NilClassпредоставленным #to_iметодом, который будет возвращать ноль для nilзначений:

unless discount.to_i.zero?
  # Code here
end

Если это discountмогут быть дробные числа, вы можете использовать #to_fвместо них, чтобы предотвратить округление числа до нуля.

Дейв Г.В.
источник
Разве это не то же самое, что ответ @ oivoodo?
Кэри Свовеланд
Не работает для произвольных объектов . "".to_i == "foo".to_i == "0".to_i == 0, Ваш метод сделает все виды непреднамеренных приведения типов. Он также потерпит неудачу, NoMethodErrorесли discountне отвечает to_i.
Том Лорд
2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

Если мы передадим "", он вернет false, тогда как пусто? возвращает истину. То же самое в случае, когда data = false blank? возвращает true для nil, false, empty или строки пробела. Так что лучше использовать бланк? метод, чтобы избежать пустой строки.

Saroj
источник
1
blank?это метод для рельсов, недоступный в ванильном рубине.
Том Лорд
Ты прав!! Я думал, что это связано с тегом "ROR", поэтому размещен здесь. Моя ошибка. Это не сработает в ванильном рубине.
Сарой
1

При работе с записями в базе данных мне нравится инициализировать все пустые значения с 0, используя помощник по миграции:

add_column :products, :price, :integer, default: 0
pastullo
источник
0

Вы можете инициализировать скидку до 0, если ваш код гарантированно не будет пытаться использовать ее до инициализации. Полагаю, это сняло бы одну проверку, я больше ни о чем не думаю.

Эд С.
источник
0
if discount.nil? || discount == 0
  [do something]
end
Абхинай Редди Кисара
источник
0

Я предпочитаю использовать более чистый подход:

val.to_i.zero?

val.to_iвернет, 0если val является nil,

после этого все, что нам нужно сделать, это проверить, равно ли окончательное значение нулю .

Ozesh
источник
-1

Альтернативное решение - использовать уточнения, например:

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if discount.nothing?
  # do something
end
RichOrElse
источник
-7

Я считаю, что следующее достаточно для рубинового кода. Я не думаю, что смогу написать модульный тест, который показал бы разницу между этим и оригиналом.

if discount != 0
end
Джефф Вальцер
источник
8
Было бы оценить, trueесли бы были скидки nil.
Эндрю Гримм