お題:文字列に出現する単語数を数えてみよう
問題:文字列no pain no gain
に出てくる単語の個数を数えて、ハッシュで表現しよう
問題については以下の記事を参考にした。 qiita.com
回答
string = 'no pain no gain' hash = Hash.new(0) string.split(' ').each { |word| hash[word] += 1}
合計すると2時間くらいかかってしまった…。まだまだレベルが足りない証拠だ。
解説
Hash.newをして空ハッシュを作る。 ただし、ここで
hash = {}
と空ハッシュを作って実行すると、以下のエラーが返ってきてしまう。
undefined method `+' for nil:NilClass
ハッシュに対して存在しないキーを指定するとnilが返り、「このメソッドは定義されてないよー」と教えてくれている。
hash = {} hash[:foo] => nil
hash = Hash.new('hello') hash[:foo] => "hello"
なので、Hash.new(0)
と最初に0を入れる。するとこうなる。
hash = Hash.new(0) p hash[:a] = 10 p hash[:b] p hash[:c] => 10 0 0 # :a以外は初期値が0になっていることがわかる
あとはsplitメソッドを使って文字列を単語で区切って配列に入れる。 eachメソッドにブロックを渡し、ブロック内ではそれぞれの単語が出てきたら、単語をキーにして値に数値の1をプラスしていく。
つまり、最初のnoが出てきたときにはその値が1になり、2回目のnoが出てきたとき、すでに最初の1があるので、それに1を足して2になる。
反省
[Ruby][解答募集]文字列に出現する単語の個数を数えてみよう - Qiita
本家の記事に投稿されているコードを見ると、皆さんdef
を使ってメソッド名をつけて引数も設定している。これがプロの作法なんだと学んだ。
Ruby入門本として有名な「チェリー本」の著者である伊藤さんもブログで次のように言っている。
これらの問題にチャレンジした方のコードを見ていると、putsやprintを多用して、出力結果を組み立てている方が多いようです。 最初の実装はそれでもよいのですが、最終的にはロジック本体と画面出力を分離して、テストコードまで追加するのが理想的です。
アウトプットのネタに困ったらこれ!?Ruby初心者向けのプログラミング問題を集めてみた(全10問) - give IT a try
つまり今回書いたコードは次のように書き直せる。
string = 'no pain no gain' def count_string(string) hash = Hash.new(0) string.split(' ').each { |word| hash[word] += 1} puts hash end count_string(string)
ただ、これだとputs hash
がメソッドの中にあるので、こっちのほうがいいのかも?
string = 'no pain no gain' @hash = Hash.new(0) def count_string(string) string.split(' ').each { |word| @hash[word] += 1} end count_string(string) puts @hash