Ruby数组的哈希。 group_by并在一行中修改

我有一系列哈希,类似于

[ {:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"} ] 

我想把它转换成这个

 { "Meat" => ["one", "two"], "Fruit" => ["Four"]} 

我试过group_by然后我得到了这个

 { "Meat" => [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}], "Fruit" => [{:type=>"Fruit", :name=>"four"}] } 

然后我不能修改它只留下名称而不是完整的哈希。 我需要在一行中执行此操作,因为对于Rails表单上的grouped_options_for_select

 array.group_by{|h| h[:type]}.each{|_, v| v.replace(v.map{|h| h[:name]})} # => {"Meat"=>["one", "two"], "Fruit"=>["four"]} 

遵循steenslag的建议:

 array.group_by{|h| h[:type]}.each{|_, v| v.map!{|h| h[:name]}} # => {"Meat"=>["one", "two"], "Fruit"=>["four"]} 

在初始数组的单次迭代中:

 arry.inject(Hash.new([])) { |h, a| h[a[:type]] += [a[:name]]; h } 
 array = [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}] array.inject({}) {|memo, value| (memo[value[:type]] ||= []) << value[:name]; memo} 

我会这样做:

 hsh =[{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}] p Hash[hsh.group_by{|h| h[:type] }.map{|k,v| [k,v.map{|h|h[:name]}]}] # >> {"Meat"=>["one", "two"], "Fruit"=>["four"]} 

使用ActiveSuport的Hash#transform_values

 array.group_by{ |h| h[:type] }.transform_values{ |hs| hs.map{ |h| h[:name] } } #=> {"Meat"=>["one", "two"], "Fruit"=>["four"]} 

@ArupRakshit回答 ,略有修改(为了清晰起见,在最后的例子中添加了该function):

 def group(list, by, at) list.group_by { |h| h[by] }.map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h end sample =[ {:type=>"Meat", :name=>"one", :size=>"big" }, {:type=>"Meat", :name=>"two", :size=>"small" }, {:type=>"Fruit", :name=>"four", :size=>"small" } ] group(sample, :type, :name) # => {"Meat"=>["one", "two"], "Fruit"=>["four"]} group(sample, :size, :name) # => {"big"=>["one"], "small"=>["two", "four"]} 

请注意,虽然问题中未提及,但您可能希望保留原始sample 。 有些答案对此有所规定,其他答案则没有。

分组后( list.group_by {...} )执行转换的部分(不修改原始样本的值)是:

 .map { |k,v| [ k , v.map {|h| h[at]} ] }.to_h 

一些提示

  1. 迭代成对的Hash of groups(第一张map ),在哪里
  2. 对于每次迭代,我们收到|group_key, array]并返回[group_key, new_array]Array (外部block ),
  3. 最后to_hArray of Array转换为Hash (这[[gk1,arr1],[gk2,arr2]...]到这个{ gk1 => arr1, gk2 => arr2, ...}

在上面的步骤(2)中没有解释一个缺失的步骤。 new_arrayv.map {|h| h[at]} v.map {|h| h[at]} ,它只是对array的每个原始Hashh )元素的值at转换(所以我们从Array of Hash es移动到一个元素Array )。

希望能帮助他人理解这个例子。