2009-10-12 18 views
20

ちょっとだけ、次の3つの行がその影響において同じでないのはなぜですか?"||" OR演算子in Rubyの条件付き

if @controller.controller_name == "projects" || @controller.controller_name == "parts" 

if @controller.controller_name == ("projects" || "parts") 

if @controller.controller_name == "projects" || "parts" 

最初は私が望む結果が得られますが、単にプロジェクトや部品よりも実際に多くのオプションが、ありますように、そのフォームを使用すると、冗長な文を作成します。他の2つはコンパクトですが、私には同じ結果を与えません。

答えて

38

正確なセマンティクスは||以下のとおりです。

  • 最初の式がnilか偽でない場合は、最初の式がnilまたはfalseの場合、それ
  • を返し、2番目の式が返し

ので、あなたの最初の式があるということになりますどのような、 @controller.controller_name == "projects"の場合、式は短絡し、trueを返します。そうでなければ、2番目の式をチェックします。 "projects" || "parts""projects"に等しいので、第2および第3の変形は実質的にif @controller.controller_name == "projects"である。あなたはIRBでこれを試すことができます:あなたが何をしたいか

>> "projects" || "parts" 
=> "projects" 

は違いが起こっているのオーダーである

if ["projects", "parts"].include? @controller.controller_name 
5

||はそう

"projects" || "parts" 

が第二の2つの例では、あなたはいつもだろうことを意味し、ヌルでない最初の文字列(この場合は「プロジェクト」)が返されます、また、オペレータを合体nullであります評価する:

IRBを焼成
if @controller.controller_name == "projects" 

、あなたはこれが起こっていることを確認することができます。

a = "projects" 
b = "parts" 

a || b 

が返すprojects

+4

実際には、 'a || =" hello "'と 'a = somefunc()|| default'のようなイディオムをサポートするための最初の文字列を提供します –

+0

あなたは本当に正しいです。 – jerhinesmith

6

です。また、||あなたはそれが2と3

にまた、あなたはより多くの試合を追加する必要がある場合は、将来的にコードを減らすために

if ['projects','parts'].include?(@controller.controller_name) 

を行うことができないと思う何をしていません。

2

非冗長ソリューションを取得する簡単な方法はある

if ["a", "b", "c"].include? x 

この実際||とは何の関係もありませんが、値はルビーに真であると考えられているというものを。間違っていなくてもすべてが真実です。

0

最初に、 "projects"と "parts"の文字列リテラルを変数@controller.controller_nameと比較します。

2つ目評価する(「プロジェクト」||「部」)「プロジェクト」 "@controller.controller_nameとを比較し、「プロジェクト」の文字列リテラルでもないfalseまたはnilまたは空の文字列と@controller.controller_name

第1にそれを比較するためでありますそれらが等しければtrueを返します。そうでなければ、の文ではtrueに等しい「パーツ」を返します。

1

論理または演算子||ブール式で動作するので、文字列に を使用すると、あなたが望むことはできません。

冗長ではなく読みやすくするために、いくつかの方法があります。

Array#includeを使用していますか?そして、単純なif文:

if ["projects", "parts"].include? @controller.controller_name 
    do_something 
else 
    do_something_else 
end 

ケース・ステートメントを使用:

case @controller.controller_name 
when "projects", "parts" then 
    do_something 
else 
    do_something_else 
end 
3

は基本的に、==他の事業者を介して配布されません。理由は、3 * (2+1)3 * 2 + 3 * 1と同じですが、乗算が加算を超えて分散することです。

a ||の値式はその引数の1つになります。したがって、2番目のステートメントは、次のものと同等です。

if @controller.controller_name == "projects" 

if (@controller.controller_name == "projects") || "ports" 
2

そこに行くいくつかの異なるものがあります:第三文は同等ですので、==よりprecedence低いのです

if @controller.controller_name == "projects" || @controller.controller_name == "parts" 

これはあなたが、私が想定していたい動作を提供します。ロジックはかなり基本的なものです:コントローラ名がどこかであるかどうかをチェックします

if ["projects", "parts", "something else..."].include? @controller.controller_name 

:のcontroler名はいずれかの「プロジェクト」または「部」

これを行う別の方法がある場合は、trueを返します。リスト。今、他の例については

if @controller.controller_name == ("projects" || "parts") 

これは、あなたがやりたいことはありません。 ("projects" || "parts")が最初に評価され(結果は「projects」になります)、コントローラー名がそれと等しいかどうかを確認するだけです。

if @controller.controller_name == "projects" || "parts" 

これはさらに奇妙なものになります。これは常に真実になります。まず、コントローラ名が "projects"に等しいかどうかをチェックします。そうであれば、ステートメントはtrueと評価されます。そうでない場合は、それ自身の "部品"を評価します。これもルビーで "真"と評価されます(ブール論理の目的では、非ゼロのオブジェクトはすべて「真」とみなされます)。