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

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

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

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

Q&A

解決済

3回答

2778閲覧

Rubyで文の中から最も長い単語を返すメソッドを表すプログラミング例がよく分からないです。

H-JURI

総合スコア42

Ruby

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

0グッド

1クリップ

投稿2015/10/16 10:47

プログラミング初心者です。
文の中から最も長い単語を返すメソッドを表すプログラミングを書けという課題で、それの解答例の意味がよくわかりません。ご教授願います。

課題の原文は
Write a method that takes in a string. Return the longest word in the string. You may assume that the string contains only letters and spaces.
You may use the String split method to aid you in your quest.
です。

解答例は

def longest_word(sentence) #longest_word(sentence)というメソッドを作る
words = sentence.split(" ") #文を配列のように単語単語に分ける

longest_word = nil #最も長い単語がない(つまり文がない)時にnilを返す

word_idx = 0 #1つ目の単語を0個目とする??
while word_idx < words.length #ある番目の単語<単語の文字数??の間繰り返す
current_word = words[word_idx] #現在の単語にある番目の単語を代入する

if longest_word == nil #もし最も長い単語ならnilを返して、下のコードを実行?? longest_word = current_word #最も長い単語として現在の単語を代入する elsif longest_word.length < current_word.length #もし上のif文の条件ではなく、最も長い単語の長さ<現在の単語の長さの場合、下のコードを実行 longest_word = current_word #最も長い単語として現在の単語を代入 end #if文を終わる word_idx += 1 #次の単語を見る

end #while文の終わり

return longest_word #longest_wordを返す
end #終わり

です。

自分なりの解説を解答のコードの右に#として書いてみました。正直曖昧ですが、??が付いているところが分からなかったところです。

??の部分をご教授願いたいです。宜しくお願いします。

最後にteratailで初めて質問させていただいたので、質問の仕方で改善するべき点があれば是非いってください。

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

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

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

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

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

guest

回答3

0

質問文にあるコードは ruby らしさ、単純さの点ではあまり良いコードとはおもえません。
でも、質問文にあるコードも理解ができるようになっておくことは必要です。

?? の部分は次のように考えると良いとおもいます。

word_idx = 0 #1つ目の単語を0個目とする??
==>
このプログラムでは word_idx を 0, 1, ... words.length - 1 と変化させて wowd をすべてスキャンしています。
ここでは while ループの入るまえに、word_idx の初期値を設定しています。

while word_idx < words.length #ある番目の単語<単語の文字数??の間繰り返す
==> words.length は 調べるべき単語の総数です。
word_idx < words.length の間、処理を繰り返します。
while 中では word_idx 番目の単語について処理をします。

if longest_word == nil #もし最も長い単語ならnilを返して、下のコードを実行??
==> while ループに入る前に longest_word = nil としています。
while ループなかで logest_word.length を参照する必要ができますが、
longest_word == nil の状態だと、logest_word.length という参照はできません。
longest_word != nil のときにだけ logest_word.length をつかった操作をするようにしています。

投稿2015/10/16 23:02

katoy

総合スコア22324

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

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

H-JURI

2015/10/17 06:02

回答ありがとうございます。 2個目の??の.lengthメソッドは文字数ではなくて単語数なのですね。混乱が解けました! そしてこの問題と解答に関してですが、プログラミング初めての人用に作られているものでRubyをベースに最低限プログラマーとして知っておいて欲しい内容も同時に学ばせたいという思惑もあるのでは、認識しています。 正直まだRubyらしさ、というものがわかりませんが、これからしっかり分かるよう勉強していきたいと思います。
guest

0

word_idx = 0はコメントの通りです。単語の配列(words)は0番目から始まるので、最初に0にしています。
while word_idx < words.lengthは配列のインデックスを一つ一つ増やしていった(word_idx += 1の部分)ときに、単語の配列の長さを超えない限り繰り返すという意味です。
if longest_word == nilの部分は、もし、まだ一つも調べていないか(つまり、一番長い単語が無い状態)を確認しています。つまりこれは、一番最初になるわけで、最初の単語は調べてきたうちの一番長い単語になるから、logest_wordへの代入を行うということの条件分岐です。

で、解答例の解説はいいのですが、解答例が悪すぎます(もっと言うと問題も悪すぎます)。解答のメソッドは1行で終わります。

Ruby

1def longest_word(sentence) 2 sentence.split.max_by{|word| word.length} 3end

問題点をいくつか述べていきます。

  1. 問題文の不備

「一番長い単語」とありますが、それが複数あった場合を想定していません。
2. splitの引数は不要
splitのデフォルトでスペース区切りです。" "は不要です。
Ruby:String#slpit
3. max_byを使わない理由が無い
ArrayがMix-inしているEnumerableにはmax_byという最大を求めるのに便利なメソッドがあります。
Ruby:Enumerable#max_by
上のコードでは配列にある単語の長さ(word.length)同士で比較し、最大になる要素を返すという意味です(最大が複数あった場合、どれが返るかは不定です)。

他にも、0からwords.lengthまで繰り返すなら、words.length.timesでいいだろうとか、そもそも、配列をeachすればいいだろうとか、まったくもってRubyらしさも無い、どっか他の言語でもやりたいんですか?という解答例です。もし、Rubyをしたくて勉強しているのであれば、その問題と解答例が載っているところは参考にしないことをお勧めします。

投稿2015/10/16 13:17

raccy

総合スコア21735

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

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

H-JURI

2015/10/17 06:08

回答ありがとうございます。 3個目の??の意味がわかった気がします!助かりました。 問題の不備もなるほど、と思いました。 そしてこの問題と解答に関してですが、プログラミング初めての人用に作られているものでRubyをベースに最低限プログラマーとして知っておいて欲しい内容も同時に学ばせたいという思惑もあるのでは、認識しています。 正直Rubyもまだまだ途中なのでこれから精進させていただきます。
guest

0

ベストアンサー

私なりの理解でコメントを入れてみました

ruby

1def longest_word(sentence) 2 words = sentence.split(" ") # 文字列をスペースを区切り文字として配列に変換 3 # (スペースが対象の場合は、単にsplit としても可) 4 5 longest_word = nil # とりあえず初期化(ループ処理開始のためのnil) 6 7 word_idx = 0 # 配列走査インデックスの初期化 8 while word_idx < words.length # words 配列の終端まで(コードブロック内の処理を)繰り返す 9 current_word = words[word_idx] # インデックス値を利用して値を取り出し、current_word を更新 10 11 if longest_word == nil 12 longest_word = current_word # longest_word がnil なので現在の値を代入 13 elsif longest_word.length < current_word.length 14 longest_word = current_word # 現在の値のほうがより長いので値を更新 15 end 16 17 # 条件に応じた値を返す形式の書き方でも可(longest_word に値が代入される) 18 # longest_word = 19 # if longest_word.nil? 20 # current_word 21 # elsif longest_word.length < current_word.length 22 # current_word 23 # else 24 # longest_word 25 # end 26 27 word_idx += 1 # インデックス値をインクリメント 28 end 29 30 return longest_word # 最長単語を返す 31 # (単にlongest_word と記述するだけでも可) 32end

似たような動作をする関数として、longest_word2 を定義してみました:

ruby

1def longest_word2(sentence) 2 desc_sorted = sentence.split.sort_by { |word| word.length }.reverse 3 # 単語の長さで昇順に並べ替えて、そのあとで逆順にする(=降順になる) 4 5 longest_word_length = desc_sorted.first.length 6 # 並べ替えた配列のアタマの単語の長さを取り出す 7 8 desc_sorted.find_all { |word| word.length.eql?(longest_word_length) } 9 # 最長単語と、それと同じ長さの単語を配列で返す 10end

実行結果:

ruby

1target = <<EOF 2Write a method that takes in a string. Return the longest word in the string. You may assume that the string contains only letters and spaces. 3You may use the String split method to aid you in your quest. 4EOF 5 6p longest_word(target) # => "contains" 7p longest_word2(target) # => ["contains"]

何か参考になれば幸いです

Links

投稿2015/10/16 12:40

gouf

総合スコア2321

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

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

H-JURI

2015/10/17 06:17

ご回答ありがとうございます。 ==nilで初期化、word[word_idx]がインデックス値で値を取り出す、等理解しやすかったです! さらにlongest_word2として新しいものの定義までしていただき大変ありがたいです。参考にさせていただきます! Rubyの学習もまだまだ最初なのでこれから頑張らさせてもらいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問