2013-06-04 86 views
2

我有散列的數組:如何映射散列數組?

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

我認爲它會得到一樣好。我很確定散列不在內存中排序,因此只有安全地獲取所需的密鑰。 – squiguy

+1

@squiguy哈希在Ruby 1.9及更高版本中保持順序。 –

+3

試圖保存六個字符,因爲這是一個「有點醜陋」是相當可疑的。 – meagar

回答

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 
+2

'.map {| x | x [:a]}'仍然是迄今爲止最好的:p – meagar

+0

@meagar是的,儘管探索選項很有趣。我上面的評論迴應了我的答案中的第一個(也許是蓋過的)條款:make objects! –

+0

@meagar任何方式來重新編寫代碼?我嘗試過'.map(&:[],:propname)',但沒有改變那工作..我只是得到語法錯誤,即使''發送'在那裏以及...椒鹽脆餅冒號!大概只能接受一個參數.. – Pysis

0

目前還不清楚你的意思是「更好」,爲什麼你認爲正確的版本是醜陋的。

你喜歡這個「更好」嗎?

arr.inject(0) { |sum, h| sum + h[:a] }