ハッシュの配列をマッピングするにはどうすればよいですか?
概要
ハッシュの配列があります:
arr = [ {:a => 1, :b => 2}, {:a => 3, :b => 4} ]
私が達成したいのは次のとおりです。
arr.map{|x| x[:a]}.reduce(:+)
しかし、それは少し醜い、または少なくとも次のようにエレガントではないと思います。
arr.map(&:a).reduce(:+)
後者は、ハッシュに a と呼ばれるメソッドがないため、間違っています。
マップ{|x|を記述するより良い方法はありますか? x[:a]}?
解決策
おそらく構造体を使用して、実際のオブジェクトを作成できます。
MyClass = Struct.new :a, :b
arr = [MyClass.new(1, 2), MyClass.new(3, 4)]
arr.map(&:a).reduce(:+) #=> 4
または、より柔軟性を高めるには、OpenStruct を使用します。
require 'ostruct'
arr = [OpenStruct.new(a: 1, b: 2), OpenStruct.new(a: 3, b: 4)]
arr.map(&:a).reduce(:+) #=> 4
もちろん、これらはいずれも既存のハッシュから構築できます。
arr = [{ :a => 1, :b => 2 }, { :a => 3, :b => 4 }]
ss = arr.map { |h| h.values_at :a, :b }.map { |attrs| MyClass.new(*attrs) }
ss.map(&:a).reduce(:+) #=> 4
oss = arr.map { |attrs| OpenStruct.new attrs }
oss.map(&:a).reduce(:+) #=> 4
または、よりクリエイティブで機能的なアプローチの場合は、次のようにします。
def hash_accessor attr; ->(hash) { hash[attr] }; end
arr = [{ :a => 1, :b => 2 }, { :a => 3, :b => 4 }]
arr.map(&hash_accessor(:a)).reduce(:+) #=> 4