each_with_objectとinjectでhashの中身を入れ替える

結局、ボヘミアン・ラプソディ見なかったので、せめてQeenの前身となったSmileのhashの中身を入れ替えて、Queenのhashにしてみました。

each_with_objectとinjectを使って、Smileのhashから、vocal、bassを務めるティム・スタッフェルの代わりにフレディ・マーキュリーとジョン・ディーコンを加えてQueenのhashを新たに作ります。


* 2019/2/27追記

コメント欄にて@QUANONさんからコメント頂いたので追記です!

今回のようなhashの入れ替えは、Hash#mergeを使うのが一般的とアドバイス頂きました。

smile = { vocal: 'tim', guitar: 'brian', bass: 'tim', drum: 'roger' }

queen = smile.merge(vocal: 'fleddie', bass: 'jhon')

=> {:vocal=>"fleddie", :guitar=>"brian", :bass=>"jhon", :drum=>"roger"}

以下に書いてるようにループで面倒な事してましたね。勉強になりました!


each_with_object

old_hash.each_with_object(初期化object) {|item, new_hash| block処理 }

初期化オブジェクトに{}を入れてhashにし、itemに(key、value)を入れてnew_hashに1つずつ入れるblock処理にします。

smile = { vocal:'tim', guitar:'brian', bass:'tim', drum:'roger' }

queen = smile.each_with_object({}) do |(key, val), member|
member[key.to_sym] =
case key
when :vocal
member[:vocal] = 'fleddie'
when :bass
member[:bass] = 'jhon'
else
val
end
end


inject

old_hash.inject(初期化object) {|new_hash, item| block処理 }

smile = { vocal:'tim', guitar:'brian', bass:'tim', drum:'roger' }

queen = smile.inject({}) do |member, (key, val)|
member[key.to_sym] =
case key
when :vocal
member[:vocal] = 'fleddie'
when :bass
member[:bass] = 'jhon'
else
val
end
member #injectの場合、ブロックでループする最後に作成中のhashを返す行が必要
end

例題はふざけてますが、元のhashを加工して違うhashとして使用する事って、たまにあると思います。