質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

8206閲覧

if文のorで分岐した際に表示されるWarningについて

yuki_90453

総合スコア326

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2016/10/19 07:19

###発生している問題・エラーメッセージ
if文において下記のように条件分岐した際、warningメッセージで出てしまいます。
試した事に記述した方法では冗長だと思うので正解では無いと思います。
動作に問題は無いのですが、なぜこのようなメッセージが出るのかわからないので質問させて頂きました。

###該当のソースコード

ruby

1 if size == "A" or "B" or "AB" 2 3 elsif size == "C" or "D" or "CD" 4 5 elsif size == "E" or "F" or "EFG" 6 7 else 8 end

###メッセージ

warning: string literal in condition

###試した事

if size == "A" or size == "B" or size == "AB" elsif size == "C" or size == "D" or size == "CD" elsif size == "E" or size == "F" or size == "EFG" else end

検索した結果、下記のURL先のページを見つけたのですが、症状も似ていました。
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1312454933

文字列を論理演算子を使用して分岐する事に問題があるという事で間違いないでしょうか?
その場合、注意メーッセージを表示されない正しい記述方法がご教授お願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ruby

1if size == "A" or "B" or "AB" 2elsif size == "C" or "D" or "CD" 3elsif size == "E" or "F" or "EFG" 4else 5end

これをrubyがどのように解釈するか段階で追ってみましょう

まず、 ( ) をつけて演算子の優先順位を明確にしてみます。

ruby

1if (size == "A") or ("B") or ("AB") 2elsif (size == "C") or ("D") or ("CD") 3elsif (size == "E") or ("F") or ("EFG") 4else 5end

となります。

ここで ruby の世界は falsenil のみがで、あとは全て 0 だろうが '0' だろうが '' だろうがであるという事を思いだしてみます。

すると。。。

ruby

1if (size == "A") or (true) or (true) 2elsif (size == "C") or (true) or (true) 3elsif (size == "E") or (true) or (true) 4else 5end

になります。。。。おーーー。なんてこったー。

さらに 各条件式は or なので、結局

ruby

1if true 2elsif true 3elsif ture 4else 5end

と書いているのと同じ事です。

なので何かおかしいですよーという意味で warning: string literal in condition というメッセージを出してくれているものだと思います。


ちなみに。。。簡潔に書くにはいくつか方法がありまして簡単なのはcase..whenを使って

ruby

1case size 2when 'A', 'B', 'AB' 3 'A' 4when 'C', 'D', 'CD' 5 'C' 6when 'E', 'F', 'EFG' 7 'E' 8else 9 '?' 10end

というのが一番わかりやすいですかね。

(rubyのcase..whenはなかなかおもしろいですよ)

投稿2016/10/19 07:31

編集2016/10/19 07:32
hana-da

総合スコア1728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki_90453

2016/10/19 07:39

早速ご返事頂きありがとうございます。 >ここで ruby の世界は false と nil のみが偽で、あとは全て 0 だろうが '0' だろうが '' だろうが真であるという事を思いだしてみます。 条件式が成り立たなくてもrubyが真として解釈するいう事でしょうか? 例えばこのsizeにHが代入されていた場合、全ての式がfalseになるわけですから、真にならないと思いますし、下記のように全てtrueとして解釈されるのもよくわかりません。 if true elsif true elsif ture else end orを使う事に問題があるのでしょうか
hana-da

2016/10/19 07:46 編集

or は左辺を評価して偽だった場合右辺を評価します。 なので size = 'H' (size == "A" or "B" or "AB") といった場合まず size に 'H' が代入され、次の行で size == "A" が評価されます。ここで size は 'H' ですので 'H' == 'A' という意味になり 偽 です。 or の左辺が 偽 なので or の右辺が評価されます 'B' です。 これは nil でも false でもないので真になります。2つめの or の右辺は真となりましたので、ここで評価は終了し最後の 'AB' は評価されず (size == "A" or "B" or "AB") の結果は 真 ('B')になります。 irbで試してみると irb(main):001:0> size = 'H' => "H" irb(main):002:0> (size == "A" or "B" or "AB") => "B" といった感じです。
yuki_90453

2016/10/19 07:45

orを使う場合、どれか必ず真になるように記述しないと行けないでしょうか? if (size == "A") or ("B") or ("AB")
maisumakun

2016/10/19 07:45

「(size == "A") or ("B") or ("AB")」と解釈されるので、そもそも「この文字列のどれか」という意味になりません。
yuki_90453

2016/10/19 07:52 編集

>or の左辺が 偽 なので or の右辺が評価されます 'B' です。 これは nil でも false でもないので真になります。。2つめの or の右辺は真となりましたので、ここで評価は終了し最後の 'AB' は評価されず (size == "A" or "B" or "AB") の結果は 真 ('B')になります。 irbで試してみると irb(main):001:0> size = 'H' => "H" irb(main):002:0> (size == "A" or "B" or "AB") => "B" この場合、H==Bとなると思うのですが、それでも無条件でtrueになるという事ですよね。 そもそもorを連続して使用するという事自体、間違っているという事でしょうか?
hana-da

2016/10/19 07:52 編集

(size == "A" or "B" or "AB") これを or を使わずに if .. else で書くと if size == 'A' else 'B' else 'AB' end と書いているのと同じような感じになるんです。。。。 2つめは 'H' == 'B' ではなく 単純に 'B' なんです。
maisumakun

2016/10/19 07:50

括弧の位置から明らかかと思ったのですが、「size==」はAにしかかからず、残りは「それ自体が」trueかfalseかで判定されます。
yuki_90453

2016/10/19 07:58

hana-da 様 なるほど、私が期待している動作としては下記のような形なんですが、 if size == 'A' else size =='B' else size =='AB' end それらを下記のように下記変えるとけ結果が変わってしまいます。 if size == "A" or size == "B" or size == "AB" elsif size == "C" or size == "D" or size == "CD" elsif size == "E" or size == "F" or size == "EFG" else end
hana-da

2016/10/19 08:03

えーっと混乱してきてました。。。 if size == "A" or "B" or "AB" elsif size == "C" or "D" or "CD" elsif size == "E" or "F" or "EFG" else end と書くと warning は出るが 期待どうりの動作をする。 if size == "A" or size == "B" or size == "AB" elsif size == "C" or size == "D" or size == "CD" elsif size == "E" or size == "F" or size == "EFG" else end と書くと確かにwarningは出なくなるが期待どうりの動作をしなくなる。 という理解でいいでしょうか?
yuki_90453

2016/10/19 08:23

hana-da 様 はい、間違いございません。
hana-da

2016/10/19 08:33

そういえば。。。 > 動作に問題は無いのですが って書いてありますしたね。。。。 irb(main):001:0> size = 'B' => "B" irb(main):002:0> if size == "A" or "B" or "AB" irb(main):003:1> 'start with A or B' irb(main):004:1> elsif size == "C" or "D" or "CD" irb(main):005:1> 'start with C or D' irb(main):006:1> elsif size == "E" or "F" or "EFG" irb(main):007:1> 'start with E or F' irb(main):008:1> else irb(main):009:1* '?' irb(main):010:1> end (irb):10: warning: string literal in condition (irb):10: warning: string literal in condition (irb):10: warning: string literal in condition (irb):10: warning: string literal in condition (irb):10: warning: string literal in condition (irb):10: warning: string literal in condition => "start with A or B" あれれれ。。。。。
hana-da

2016/10/19 08:37 編集

いやいや。いいんだ。 (1) irb(main):011:0> size = 'C' => "C" irb(main):012:0> if size == "A" or "B" or "AB" irb(main):013:1> 'start with A or B' irb(main):014:1> elsif size == "C" or "D" or "CD" irb(main):015:1> 'start with C or D' irb(main):016:1> elsif size == "E" or "F" or "EFG" irb(main):017:1> 'start with E or F' irb(main):018:1> else irb(main):019:1* '?' irb(main):020:1> end (irb):20: warning: string literal in condition (irb):20: warning: string literal in condition (irb):20: warning: string literal in condition (irb):20: warning: string literal in condition (irb):20: warning: string literal in condition (irb):20: warning: string literal in condition => "start with A or B" (2) irb(main):021:0* size = 'EFG' => "EFG" irb(main):022:0> if size == "A" or "B" or "AB" irb(main):023:1> 'start with A or B' irb(main):024:1> elsif size == "C" or "D" or "CD" irb(main):025:1> 'start with C or D' irb(main):026:1> elsif size == "E" or "F" or "EFG" irb(main):027:1> 'start with E or F' irb(main):028:1> else irb(main):029:1* '?' irb(main):030:1> end (irb):30: warning: string literal in condition (irb):30: warning: string literal in condition (irb):30: warning: string literal in condition (irb):30: warning: string literal in condition (irb):30: warning: string literal in condition (irb):30: warning: string literal in condition => "start with A or B" (1)(2)ともに期待した動作でしょうか?
yuki_90453

2016/10/19 08:42

hana-da 様 今気づきました。。。通りで同じ結果ばかりだと思ったら。。。 1点お聞きしたいのですが、下記のタグですが分岐方法はorのような感じになるのでしょうか? その場合、また同じミスになってしまいますので。。。 case size when 'A', 'B', 'AB' 'A' when 'C', 'D', 'CD' 'C' when 'E', 'F', 'EFG' 'E' else '?' end
hana-da

2016/10/19 08:44

teratailさんは一問一答を望んでおられるようですので別の質問は新規に質問を立てた方がいいと思います。。。。(´・ω・`)ショボーン
yuki_90453

2016/10/19 08:48

hana-da 様 そうですね、少しお待ち下さい。
guest

0

同じ値による多重分岐は、普通はcase+whenを使います。

Ruby

1case size 2when "A","B","AB" 3 ~~~ 4when "C","D","CD" 5 ~~~ 6when "E","F","EFG" 7 ~~~ 8else 9 ~~~ 10end

投稿2016/10/19 13:30

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「文字列のどれかに一致する」ということを判定したいなら、Array#include?るりま)というのでもすっきり書けます。

rb

1# 単純な配列で 2if ['A', 'B', 'AB'].include?(str) 3 # 略 4elsif ['C', 'D', 'CD'].include?(str) 5 # 略 6end 7 8# 配列リテラルをシンプルにしてみる 9# (動作は上の例と同じです) 10if %w|A B AB|.include?(str) 11 # 略 12elsif %w|C D CD|.include?(str) 13 # 略 14end 15

投稿2016/10/19 07:54

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

文字列を論理演算子を使用して分岐する事に問題がある

はい。リンク先の回答でも説明されていますが、
おそらく質問者の方の意図通りに動作しません。

演算子の優先順位などの問題があります。
具体的には、下記コードの挙動を比較してください。

(質問文と同じようなコードですが、
見やすさのため簡略化しました)


Ruby

1size = 'C' 2if size == 'A' or 'B' 3 p 'true' 4else 5 p 'false' 6end 7# => true 8 9size = 'C' 10if size == 'A' or size == 'B' 11 p 'true' 12else 13 p 'false' 14end 15# => false

投稿2016/10/19 07:35

編集2016/10/19 07:41
LLman

総合スコア5592

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki_90453

2016/10/19 07:42

ご返事頂きありがとうございます。 そうですね、確認して見ると期待した通りの動作をしていませんでした。 なぜ、1つ目の条件式はAでもBでもないのにtrueになるのでしょうか?
LLman

2016/10/19 07:54

>なぜ、1つ目の条件式はAでもBでもないのにtrueになる 演算子の優先順位という、約束事がそうなってるからですね。 読み書きだけで言えば、理屈抜きで覚えるしかないですが、 あえてもう少し掘り下げれば、言語処理系を作る都合からです。
hana-da

2016/10/19 07:55

おそらく size == 'A' or 'B' が size == ('A' or 'B') のように見えるんでしょうが (size == 'A') or 'B' という風に結合します。 10 x 5 + 2 は (10 x 5) + 2 = 52 ですよね? 10 x (5 + 2) = 70 ではないですよね。? 演算子には優先順位があるのです。
yuki_90453

2016/10/19 08:27

>size == ('A' or 'B') のように見えるんでしょうが (size == 'A') or 'B' という風に結合します。 なるほど、すっきりしました。 理屈ぬきで覚えるしかないですね、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問