web-dev-qa-db-ja.com

「||」を理解するOR演算子if =条件式Ruby

簡単に言えば、次の3行の影響が同じではないのはなぜですか?

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

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

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

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

34
steven_noble

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

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

最初の式がうまくいくのは、@controller.controller_name == "projects"、式は短絡してtrueを返します。そうでない場合は、2番目の式をチェックします。 2番目と3番目のバリアントは基本的にif @controller.controller_name == "projects"、以来"projects" || "parts"等しい"projects"。あなたはirbでこれを試すことができます:

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

あなたがやりたいことは

if ["projects", "parts"].include? @controller.controller_name
56
Martin DeMello

違いは何が起こっているかの順序です。 ||も2と3であなたが思っていることをやっていません。

あなたもできる

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

一致するものをさらに追加する必要がある場合に、将来コードを減らすため。

7
Jim

||もnull合体演算子なので、

"projects" || "parts"

nullではない最初の文字列(この場合は「プロジェクト」)を返します。つまり、2番目の2つの例では、常に評価されます。

if @controller.controller_name == "projects"

Irbを起動すると、これが起こっていることを確認できます。

a = "projects"
b = "parts"

a || b

projectsを返します

6
jerhinesmith

そこにはいくつかの異なることがあります:

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

これにより、私が想定しているとおりの動作が得られます。ロジックは非常に基本的です。コントローラー名が「projects」または「parts」の場合、trueを返します

これを行う別の方法は次のとおりです。

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

これにより、コントローラー名がリスト内のどこかにあるかどうかが確認されます。

次に、他の例について説明します。

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

これはあなたが望むことをしません。最初に("projects" || "parts")(「プロジェクト」になります)を評価し、コントローラー名がそれに等しいかどうかのみをチェックします。

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

これはさらに奇妙になります。これは常に真になります。コントローラー名が「プロジェクト」に等しいかどうかを最初にチェックします。その場合、ステートメントはtrueと評価されます。そうでない場合は、それ自体で「パーツ」を評価します。これは、Ruby(ブールロジックの目的上、非nilオブジェクトはすべて「真」と見なされます)で「真」と評価されます)

4
madlep

基本的に、==は他の演算子に分散しません。 3 * (2+1)3 * 2 + 3 * 1と同じ理由は、乗算が加算に分配されるためです。

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

if @controller.controller_name == "projects"

||より低い precedence より==なので、3番目のステートメントは次と同等です:

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

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

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

これは、実際には||とは関係ありませんが、Rubyで真であると見なされる値は何ですか。すべてがfalseを保存し、nilはtrueです。

2
Logan Capaldo

論理OR演算子||ブール式で動作するため、文字列で使用しても、望みどおりにはなりません。

あなたが望むものを達成するいくつかの方法があり、それはより冗長で読みやすいです。

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
1
Lars Haugseth

最初に、「projects」および「parts」文字列リテラルを@controller.controller_name変数と比較します。

2つ目は、「projects」文字列リテラルがfalseまたはnilでも空の文字列でもないため、「projects」である(「projects」||「parts」)を評価し、@controller.controller_nameと比較します。

3番目は@controller.controller_nameと "projects"を比較し、等しい場合はtrueを返し、等しくない場合はtrueステートメントのifと等しい "parts"を返します。

0
vava

多くの人がinclude?比較を好むようです。

.in?演算子を使用することを好みます。ずっと簡潔です。また、より読みやすく、arrayに質問をしないため、質問したい変数に質問をします:あなたの場合、controller name

@controller.controller_name.in? ["projects", "parts"]

または、さらに良い

@controller.controller_name.in? %w[projects parts]
0
Victor