我有一系列哈希:
arr = [ {:a => 1, :b => 2}, {:a => 3, :b => 4} ]
我想要实现的目标是:
arr.map{|x| x[:a]}.reduce(:+)
但我觉得它有点难看,或者至少不那么优雅:
arr.map(&:a).reduce(:+)
后一个错误是因为哈希中没有名为a
的方法。
有没有更好的方法来撰写map{|x| x[:a]}
?
答案 0 :(得分:1)
您可以制作实际的对象,可能使用Struct:
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
答案 1 :(得分:0)
目前还不清楚你的意思是“更好”,为什么你认为正确的版本是丑陋的。
你喜欢这个“更好”吗?
arr.inject(0) { |sum, h| sum + h[:a] }