はじめに
Rubyには色んなメソッドがあります。
そこには普通のアルゴリズムを解く中では触れないような処理ができるメソッドなど。
今回は、「tapメソッド」について色々試してみて感じたことについてまとめます。
このメソッドはそこまで率先して使わなくても良いかなって思うメソッドですが、使い方がわかると使いたくなるように感じるメソッドでした。
いろんなメソッドを使いこなせるようになるとアルゴリズムを解くのも楽しくなると感じています。
本記事が参考になると幸いです。
tapメソッドについて
概要
tapは、レシーバ自身をブロックに渡して処理し、ブロックの戻り値ではなくレシーバ自身を返すメソッドです。
実際に使ってみたコード集
ここから実際にアルゴリズムを解いて使ったやり方についてまとめます。
文字列作成
まず文字列の操作で行います。
通常
シンプルにhogehogeのテキストを追加して、最後に出力するプログラムです。
text = "hogehoge"
results = ""
text.each_char { |c| results << c }
puts text
# 結果 -> hogehoge
tap
次にtapメソッドを使って、hogehogeのテキスト追加プログラムと同じ出力になるように試してみます。
text = "hogehoge"
results = "".tap { |result| text.each_char { |c| result << c } }
puts results
# 結果 -> hogehoge
所感
tapを使うことで、配列を初期化してから処理するという流れを1つの式にまとめられます。
一方で、tapのブロックが入ることで、かえってコードが読みづらくなる場合もあると感じました。
簡単な文字列操作だったら、tapは不要かもしれないです。
配列操作
次に配列操作で行います。
通常
簡単なおみくじのプログラムを作ってみます。
omikuji = ["大吉", "中吉", "小吉", "吉", "凶"]
results = []
5.times { results << omikuji.sample }
p results
# 結果(例) -> ["中吉", "小吉", "吉", "大吉", "小吉"]
tap
次にtapメソッドを使って、おみくじプログラムを作ってみます。
omikuji = ["大吉", "中吉", "小吉", "吉", "凶"]
results = [].tap { |results| 5.times { results << omikuji.sample } }
p results
# 結果(例) -> ["凶", "大吉", "吉", "中吉", "吉"]
所感
配列もtapを使うと初期化のための変数宣言するための1行削減されてコード記述量の減少しました。
簡単な処理であれば、tapメソッドを使う必要はないかもしれないですが、もしも複雑な処理で配列操作を用いるなら、tapメソッドを使って実装するのも良いと思いました。
ハッシュ操作
最後にハッシュ操作で使います。
通常
出現した文字の数を記録するプログラムを作ってみます。
text = "hogehogehoge"
results = {}
text.each_char { |c| results[c] != nil ? results[c] += 1 : results[c] = 1 }
p results
# 結果 -> {"h"=>3, "o"=>3, "g"=>3, "e"=>3}
tap
text = "hogehogehoge"
results = {}.tap { |result| text.each_char { |c| result[c] != nil ? result[c] += 1 : result[c] = 1 } }
p results
# 結果 -> {"h"=>3, "o"=>3, "g"=>3, "e"=>3}
所感
ハッシュもtapを使うと初期化のための変数宣言するための1行削減されてコード記述量の減少しました。
ハッシュも複雑な処理を実装するならtapメソッドを使って実装するのも良いと思いました。
良さげな使い道
最初に初期化のために変数を用意すると思うが、それすらも減らして、コード記述量を減らすと良い気がします。
また、長い処理の途中で結果を確認する際に役立ちそうです。
参考プログラム▼
配列を2つ合体させながら、特定の文字列のみ選択して、文字ごとの出現回数をハッシュでまとめるプログラム例です。
text_a = ["hoge", "hgoe", "hhge", "oge", "hoge"]
text_b = ["hhge", "hoge", "hhee", "hoho", "hoge"]
results = {}.tap do |result|
(text_a + text_b)
.tap { |texts| p texts }
.select { |text| text == "hoge" }
.tap { |texts| p texts }
.join
.tap { |string| p string }
.each_char { |c| result[c] != nil ? result[c] += 1 : result[c] = 1 }
end
p results
# 出力結果▼
# ["hoge", "hgoe", "hhge", "oge", "hoge", "hhge", "hoge", "hhee", "hoho", "hoge"]
# ["hoge", "hoge", "hoge", "hoge"]
# "hogehogehogehoge"
# {"h"=>4, "o"=>4, "g"=>4, "e"=>4}
メソッドチェーンで処理を加えたらtapメソッドでその都度中身を確認できるようになっています。
おわりに
tapメソッドを使うことで最初の初期化で使うべき変数がなくなったり、途中で出力結果を確認するなどして、デバッグしやすくなるのがわかりました。
そこまで優先して使うメソッドかと言われるとそうでもないと思います。
しかしながら、いろんなメソッドを使いこなせるというのもアルゴリズムやプログラミングの上達につながると思っています。
引き続き新しいメソッドを試して、アルゴリズムや実装の引き出しを広げていこうと思います。