Ruby
RubyOnRails

【翻訳】あまり知られてないけど便利なRubyのメソッド7選

More than 1 year has passed since last update.

Ruby学習の一環として、週に1度Ruby関連のブログ記事(英語)を翻訳しています。
今回は便利なメソッド集。

原文:7 Little-Known Ruby Methods To Help You Write Better Code

↓以下本文↓


Rubyのメソッドを正しく使えば、もっと楽になるって知ってました?
より多くのメソッドを知れば知るほど、より良いコードをより速く書くことができるようになります(パフォーマンス/クオリティ両方の面で)。
というわけで、今日はあまり知られていない便利なメソッドを7つ紹介したいと思います。

Integer#digits メソッド(Ruby 2.4)

これはRuby 2.4から導入されたメソッドで、数字の各桁を取り出したい時に便利です。
注:Ruby2.4をまだよく知らない方へ。2.4ではFixnumBignumIntegerに吸収されました。

数字を配列のように扱って要素が指定できそうな気がするかもしれません。

2[0]
# 0
2[1]
# 1

しかし実際には桁の値ではなく、2進数に変換した場合のビットの値が返ってきます。
なので、digitsメソッドが登場するまでのよくある解決方法は、数字を文字列に変換し、charsメソッドを使って配列に入れて、そして最後に文字列を数字に再度変換する、というものでした。

【例】

123.to_s.chars.map(&:to_i).reverse

[3, 2, 1]

しかし、digitsメソッドが登場したことで、こう書くだけでよくなりました。

123.digits

[3, 2, 1]

こちらの方がずっといいですよね。

Tapメソッド

オブジェクトを生成して、メソッドをいくつか呼び出した後に同じオブジェクトを返したい時ってありますよね。

こう書かざるを得ないでしょうかね。

user = User.new
user.name = "John"
user

問題は、この一時変数をどう扱えば良いのかということ。
こんな時こそ tap メソッドの出番です!
tap メソッドを使うとこんな風に書けます。

User.new.tap { |user| user.name = "John" }

これで一時変数を使わずにすみます。やったね!

Array#values_at

配列もしくはハッシュから不連続の複数の値を取り出したい時はこう書いているかもしれません。

arr = [1,2,3,4,5]
a, b, c = arr[0], arr[1], arr[4]

これが、values_atメソッドを使うとこのように書けます。

arr = [1,2,3,4,5]
a, b, c = arr.values_at(0, 1, 4)

ハッシュに使うこともできます。

hash = {bacon: 300, chocolate: 200}
p hash.values_at(:bacon, :chocolate)
# [300, 200]

Hash#transform_values(Ruby 2.4)

何らかの事情により、ハッシュの全ての値を変更したいとしましょう。
そんな時はArray#mapを使う人が多いんじゃないかと思います。

mapの問題は、ハッシュの代わりに配列の配列(多次元の配列)が返ってきてしまうという点。ここではHash#mapが使えます!

なので解決策の一つは、こうですね。

h = {bacon: 200, coconut: 300}
h.each { |k, v| h[k] = v*2 }

今回の例では、それぞれの値に2をかけています。

結果はこう。

{:bacon=>400, :coconut=>600}

でもRuby2.4以降なら、もっといい方法があります。

h.transform_values! { |v| v * 2 }

これはもともとRailsで使われていたメソッドで、今ではRailsのフレームワーク外でも使えるようになりました:)

Kernel#itself (Ruby2.2)

もし、一見あまりパッとしたメソッドに見えないなと思ったとしたら、私も同意見です。

でもまあいくつか便利な例を見てみてください。

例えば単語の繰り返しを含む配列があり、その回数を数えたいとしましょう。

やり方は色々ありますが、このケースはKernel#itselfを試すのにぴったりです。

【例】

words = %w(cat cat tiger dog cat)
words.group_by(&:itself).transform_values(&:size)
Hash#transform_values!と組み合わせていることもお忘れなく!

もしtransform_valuesが使えなければ、こう書くこともできます。

words
  .group_by(&:itself)
  .each_with_object({}) { |(k,v), hash| hash[k] = v.size }

Array#count

ただ数えたいだけのときってありますよね。

いつものcounter + loopの代わりに、countメソッドが使えます!

【例】

letters = %w(a a a b c d a)
letters.count("a")
# 4

配列の場合はブロックも引数に取ることができるので、もっと複雑なこともできます。

numbers = [1,2,3,4,5,6]
numbers.count(&:even?)
# 3

Enumerable#cycle

なんらかのパターンを繰り返したい?もしくはシンプルにon/offを切り替えたい?
なら、Enumerable#cycleがぴったりです!

【例】

array = %w(a b c)

# Same as array * 3
array.cycle(3).to_a

私の場合は、「スイッチ」や「切り替え(toggle)」オブジェクトを生成する時に重宝しています。

switch = %w(on off).cycle
switch.next

「スイッチ」の値を変更する際に現在の値を確認する必要がない、というのがこのメソッドの便利なところですね。nextを呼び出せば、Rubyが自動的に次の値を判断してくれます🙂

まとめ

さて、今回は以下のメソッドを紹介しました
Integer#digits, Kernel#tap, Array#values_at, Hash#transform_values, Kernel#itself, Array#count, Enumerable#cycle.

もし既にご存知でしたら素晴らしい!もし知らなかったのであれば、便利だと思ってもらえれば幸いです🙂