Tech Racho エンジニアの「?」を「!」に。
  • 開発

Ruby: Kernel#itselfの美学(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Ruby: Kernel#itselfの美学(翻訳)

最近私は、Rubyでよくある問題を解決しました。コレクションで渡される項目ごとの頻度をカウントするという問題です。この問題の解決方法はいくつか考えられます。最初は以下のようにEnumerable#injectまたはEnumerable#each_with_objectを用い、空のハッシュをアキュムレータの値として使いました。

collection.each_with_object({}) { |item, accum| accum[item] = accum[item].to_i + 1 }

ハッシュのデフォルト値を用いて、もう少しスマートな方法に変えました。

collection.each_with_object(Hash.new(0)) { |item, accum| accum[item] = accum[item] + 1 }

これはこれでなかなかいいのですが、これよりずっと美しい方法があります。

Rubyの美学

この問題を解決する興味深い方法のひとつは、Enumerable#group_byを使う方法です。単に要素をそれら自身でグループ化し、各項目の頻度をカウントします。以下は実装方法の1つです。

collection.group_by { |item| item }.map { |key, value| [key, value.count] }.to_h

しかしながら、特にRubyの標準から見てもう少し何とかできそうな気がします。そしてもっといい方法に気づきました。Ruby 2.4ではActiveSupportのcore extensionの非常に便利なHash#transform_valuesが採り入れられました。これを応用すれば、次のように書き換えることができます。

collection.group_by { |item| item }.transform_values(&:count)

ずいぶんよくなりましたが、group_by { |item| item }のあたりをもう少し何とかできそうです。こういう場合に便利な道具がRubyにあるでしょうか?

そう、あるのです!Ruby 2.2で導入されたKernel#itselfは、単にそれ自身を返します。これを使うというアイデアは一見奇妙に思われるかもしれませんが、これがどんぴしゃりはまるのです。

collection.group_by(&:itself).transform_values(&:count)

コードがここまで美しくなりました。

まとめ

Rubyコードは気持ちよく読めることで特に知られています。そして私はRubyとこれほど長い間付き合っていても、Kernel#itselfのようにRubyという言語にトータルな美しさを付け加えるささやかなものを発見するたびに、言い知れない喜びに浸ります。

その後

関連記事

Rubyのシンボルをなくせるか考えてみた(翻訳)

Rubyのクラスメソッドをclass << selfで定義している理由(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。