2013-09-20 1 views
14

У меня есть массив хэшей, что-то вроде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

Там в [ 'option_groups_from_collection_for_select'] (http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-option_groups_from_collection_for_select) помощник. – Stefan

ответ

16
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"]} 
+4

Последний блок может быть записан как '{| _, v | v.map {|! ч | h [: name]}} ' – steenslag

+0

@steenslag Спасибо. Я забыл об этом. – sawa

+0

... или 'each_value ...', и не вижу, почему '!'. –

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

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

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

Ницца! (Но ваша преамбула звучит как барабанный ролл. :-)) –

+2

Ваш ответ дал мне больше понимания прохлады «впрыскивания». Благодаря! –

1

Я хотел бы сделать, как показано ниже:

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

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

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