[Ruby] each_with_objectもmapも使わずにto_hだけで配列をハッシュに変換する

こんにちは、hachi8833です。

Web開発チームのtsunekawaさんに教えていただいた方法をメモします。

to_hだけで配列をハッシュに変換できる

早速試してみましょう。

each_with_objectメソッドの場合

[["Alice", 50], ["Bob", 40], ["Charlie", 70]].each_with_object({}) do |(key, value), hash|
  hash[key] = value
end

map.to_hで書いた場合

[["Alice", 50], ["Bob", 40], ["Charlie", 70]].map.to_h

to_hだけで書いた場合

[["Alice", 50], ["Bob", 40], ["Charlie", 70]].to_h

実行結果

確かに3つとも同じ結果になってますね。

#to_hについて

せっかくなので、「to_hだけで書いた場合」で呼ばれているto_hがどこにあるのかを確認してみましょう(参考: RubyのIRBやpryでメソッドの定義元をすっと調べる方法)。

to_hだけで書いた場合

素のpryで実行していることからもおわかりのように、「to_hだけで書いた場合」で呼ばれているのはRuby標準ライブラリのArray#to_hでした。

なお、Array#to_hが導入されたのはRuby 2.1.0からなので、意外と新しいんですね(参考: Ruby 2.1.0リリース!注目の新機能を見てみましょう)。

map.to_hで書いた場合

順序が逆になりますが、map.to_hの場合もついでに調べてみました。

予想どおり、こちらはRuby標準ライブラリのEnumerable#to_hが呼ばれています。

今回のパターン「[["Alice", 50], ["Bob", 40], ["Charlie", 70]]」では、Array#to_hEnumerable#to_hは同じ結果になりましたが、レシーバーの内容によっては同じにならないかもしれません。

参考

たとえばRailsだとActive Support core_extにもXMLConverter#to_hがあり、実際にはXMLConverter#deep_to_hを呼んでいます。

    def to_h
      deep_to_h(@xml)
    end

ほかにもAction Controller(Action Pack内)のmetal/strong_parameters.rbにもParameters#to_hがあります。

    def to_h
      if permitted?
        convert_parameters_to_hashes(@parameters, :to_h)
      else
        slice(*self.class.always_permitted_parameters).permit!.to_h
      end
    end

Rails環境では他にもさまざまなライブラリにto_hがあります。

参考

関連記事

Ruby 2.1.0リリース!注目の新機能を見てみましょう

ActiveRecordのモデルに対してto_hashを出来るようにする。

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ

BPSアドベントカレンダー