我正在尋找一個簡明的方法來檢查一個值,看它是零還是零。目前我做的是這樣的:「零或零」的最佳紅寶石成語
if (!val || val == 0)
# Is nil or zero
end
但這似乎很笨拙。
我正在尋找一個簡明的方法來檢查一個值,看它是零還是零。目前我做的是這樣的:「零或零」的最佳紅寶石成語
if (!val || val == 0)
# Is nil or zero
end
但這似乎很笨拙。
對象有一個nil? method。
if val.nil? || val == 0
[do something]
end
或者,僅僅用一個指令:
[do something] if val.nil? || val == 0
小心使用「或」和「和」,順便說一下,它們具有不同的且非常低的優先級與||相比和&&。請參閱http://blog.jayfields。com/2007/08/ruby-operator-precedence-of-and-which.html的一些評論。 – 2008-10-16 19:26:04
我同意這個問題中的「嗅覺」的一些海報,但對我來說這更像是一種紅寶石般的方式。 – Jonke 2008-10-16 20:20:29
`或`的優先級在這裏不需要任何parens,並且會完全自然地讀給一位經驗豐富的Rubyist。唯一被`||`與`或`咬過的人是從未編程過Perl的人:) – ephemient 2008-10-16 21:42:22
我相信你的代碼是不正確的;它實際上會測試三個值:nil
,false
和零。這是因爲!val
表達式適用於所有值爲false的值,在Ruby中爲nil
和false
。
我可以想出現在最好的是
if val == nil || val == 0
# do stuff
end
這當然不是很聰明,但(很)清楚。
你或許可以假定所討論的變量是一個數字。如果你甚至不知道它是布爾型還是數值型,那麼代碼中存在更大的問題。 – 2008-10-16 17:32:45
我會用.nil? not ==零 – RichH 2008-10-16 21:08:17
首先,我認爲這是關於您可以檢查特定條件的最簡潔的方式。
其次,對我來說,這是一種代碼氣味,表明您的設計中存在潛在的缺陷。通常零和零不應該意味着同樣的事情。如果可能的話,您應該嘗試消除在您打開此代碼之前val不可能爲零的可能性,無論是通過檢查方法的開頭還是其他機制。
你可能有一個完全合法的理由來做到這一點,在這種情況下,我認爲你的代碼是好的,但我至少會考慮嘗試擺脫零檢查,如果可能的話。
非常正確的代碼氣味! +1 可能考慮查看NullObject模式http://en.wikipedia.org/wiki/Null_Object_pattern – abyx 2009-11-06 19:57:53
您可以使用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
不建議作爲修改對象是困難的同事跟蹤,並且可以使你的代碼不可預知他人。
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
我定義處理這一個 「是什麼?」方法,然後我可以在不同的類上實現不同的方法。所以對於Array而言,「是嗎?」意味着「大小> 0」;對於Fixnum來說,它意味着「self!= 0」;對於字符串,它的意思是「self!=''」。當然,NilClass定義「是?」只是返回零。
爲了儘可能地道,我建議這樣做。
if val.nil? or val == 0
# Do something
end
因爲:
val ||= 0
if val == 0
# do something here
end
如果你很喜歡在結尾帶有問號的方法名稱:
if val.nil? || val.zero?
# do stuff
end
你的解決方案是好的,因爲有一些其他的解決方案。
如果你不小心,Ruby可以讓你搜索一個可以做所有事情的好方法。
,如果你喜歡,你可以使用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
這不正是很好的OOP,但它是非常靈活的,它的工作原理。無論如何,我的if
通常最終爲case
。
當然Enum.any?
/Enum.include?
樣的作品太...如果你想獲得真正的神祕:
if [0, nil].include? val
#do stuff
end
做的正確的事情當然是定義一個方法或函數。或者,如果你必須用許多值來做同樣的事情,那麼使用這些好的迭代器的組合。
另一種解決方案:
if val.to_i == 0
# do stuff
end
nil.to_i返回零,所以我經常這樣做:
val.to_i.zero?
然而,你會得到一個異常,如果val爲曾經的對象沒有的respond_to #to_i。
我真的很喜歡Rails blank?
這種方法,但它不會爲0
返回true
。所以,你可以添加你的方法:
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
這是非常簡潔:
if (val || 0) == 0
# Is nil, false, or zero.
end
它的工作原理,只要你不介意對待false
與nil
相同。在我所從事的項目中,這種區別只是偶爾發生的。剩下的時間我個人更喜歡跳過.nil?
並且代碼略短。
[更新:我不再寫這種東西了。它的作品,但太神祕了。我試圖通過改變我所做的幾個地方來糾正我的錯誤。]
順便說一下,我沒有使用.zero?
,因爲如果val
是字符串,這會引發異常。但如果你知道情況並非如此,.zero?
會很好。
取代猴子修補類,you could use refinements從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
Refinements were changed在最後一分鐘被限制到該文件。所以前面的例子可能已經證明了這一點,這是行不通的。
class Car
using NilOrZero
end
紅寶石2.3.0開始,你可以用Numeric#nonzero?
結合安全導航操作符(&.
)。 &.
返回nil
如果實例是nil
和nonzero?
- 如果數量爲0
:
unless val&.nonzero?
# Is nil or zero
end
或後綴:
do_something unless val&.nonzero?
簡短清晰
[0, nil].include?(val)
的最佳捷徑應該是
if val&.>(0)
# do something
end
對於val&.>(0)
當val爲零,因爲>基本上也是一個方法,零等於在紅寶石假它返回零。它在val == 0
時返回false。
這個計算結果爲true的零和零:nil.to_s.to_d == 0
應該發生什麼,如果VAL等於`FALSE`? – 2010-09-29 06:21:04