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"}] }

а затем я не могу изменить его, чтобы оставить только имя, а не полный хеш. Мне нужно сделать это в одной строке, потому что для grouped_options_for_select в форме Rails.

Ответы

Ответ 1

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"]}

Ответ 2

В одной итерации над исходным массивом:

arry.inject(Hash.new([])) { |h, a| h[a[:type]] += [a[:name]]; h }

Ответ 3

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

Ответ 4

Я бы сделал следующее:

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"]}

Ответ 5

Использование ActiveSuport Hash#transform_values:

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