nekoTheShadow’s diary

IT業界の片隅でひっそり生きるシステムエンジニアです(´・ω・`)

each_with_objectの便利さに開眼した。

説明しづらくて申し訳ないのですが、rubyの勉強中に次のような処理をしたいとなりました。

hash = {}
(0..2).each do |num|
  hash[num] = num
end
p hash #=> {0=>0, 1=>1, 2=>2}

何らかのオブジェクトをループでまわして、ハッシュに突っ込んでいくわけです。
動いているか動いていないかという観点に立つと、これでもよいのですが、なんというか……
美しくない!
何とかならないかと試行錯誤していきます。

1.inject

まず中毒者愛用者も多いinject
rubyの好きなメソッドランキングがあればたぶん上位に入るでしょう(偏見)
とりあえずさらっと書いてみるのですが……

hash = (0..2).inject({}){|num,hash| hash[num] = num}
p hash #=> error

実はこれではだめなのです。
その理由については後日書くつもりですが、どうしてもinjectでやりたい場合は次のような書き方をする必要があります。

hash = (0..2).inejct({}) do |hash,num|
  hash[num] = num
  hash
end
p hash #=> {0=>0, 1=>1, 2=>2}

次はうまくいきましたね。
しかしこれでもまだ美しくない。

2.each_with_object

というわけでいろいろ検索の末に行き着いたのが、each_with_object
これは引数のオブジェクトと要素を評価して最後に引数のオブジェクトを返してくれるメソッドです。
これならもしや……

hash = (0..2).each_with_object({}){|num,hash| hash[num] = num}
p hash #=> {0=>0, 1=>1, 2=>2}

うまくいきましたね。
これならわたくしの美的センス(笑)にもばっちり適合します。
ちなみにwith_objectというメソッドもあるので、each以外のメソッドで同じようなことがしたいというときには役立つはず。
よい例は全く浮かびませんでしたが(´・ω・`)