如何映射哈希数组?

Xia*_*Jia 7 ruby arrays hash

我有一个哈希数组:

arr = [ {:a => 1, :b => 2}, {:a => 3, :b => 4} ]
Run Code Online (Sandbox Code Playgroud)

我想要实现的是:

arr.map{|x| x[:a]}.reduce(:+)
Run Code Online (Sandbox Code Playgroud)

但我认为它有点丑陋,或者至少没有那么优雅:

arr.map(&:a).reduce(:+)
Run Code Online (Sandbox Code Playgroud)

a后一种是错误的,因为哈希中没有调用任何方法。

有没有更好的写作方法map{|x| x[:a]}

And*_*all 4

您可以制作实际的对象,可能使用Struct

MyClass = Struct.new :a, :b
arr = [MyClass.new(1, 2), MyClass.new(3, 4)]
arr.map(&:a).reduce(:+)  #=> 4
Run Code Online (Sandbox Code Playgroud)

或者为了获得更大的灵活性,可以使用OpenStruct

require 'ostruct'
arr = [OpenStruct.new(a: 1, b: 2), OpenStruct.new(a: 3, b: 4)]
arr.map(&:a).reduce(:+)  #=> 4
Run Code Online (Sandbox Code Playgroud)

当然,其中任何一个都可以从现有的哈希值构建:

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
Run Code Online (Sandbox Code Playgroud)

或者,对于更具创意、更实用的方法:

def hash_accessor attr; ->(hash) { hash[attr] }; end
arr = [{ :a => 1, :b => 2 }, { :a => 3, :b => 4 }]
arr.map(&hash_accessor(:a)).reduce(:+)  #=> 4
Run Code Online (Sandbox Code Playgroud)

  • `.map { |x| x[:a] }` 仍然是迄今为止最好的:p (7认同)