Ruby array of hash. group_by and modify in one line
16,042
Solution 1
array.group_by{|h| h[:type]}.each{|_, v| v.replace(v.map{|h| h[:name]})}
# => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
Following steenslag's suggestion:
array.group_by{|h| h[:type]}.each{|_, v| v.map!{|h| h[:name]}}
# => {"Meat"=>["one", "two"], "Fruit"=>["four"]}
Solution 2
In a single iteration over initial array:
arry.inject(Hash.new([])) { |h, a| h[a[:type]] += [a[:name]]; h }
Solution 3
Using ActiveSuport's Hash#transform_values
:
array.group_by{ |h| h[:type] }.transform_values{ |hs| hs.map{ |h| h[:name] } }
#=> {"Meat"=>["one", "two"], "Fruit"=>["four"]}
Solution 4
array = [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"}]
array.inject({}) {|memo, value| (memo[value[:type]] ||= []) << value[:name]; memo}
Solution 5
I would do as below :
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"]}
Related videos on Youtube
Author by
jtomasrl
Updated on June 17, 2022Comments
-
jtomasrl about 2 years
I have an array of hashes, something like
[ {:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}, {:type=>"Fruit", :name=>"four"} ]
and I want to convert it to this
{ "Meat" => ["one", "two"], "Fruit" => ["Four"]}
I tried
group_by
but then i got this{ "Meat" => [{:type=>"Meat", :name=>"one"}, {:type=>"Meat", :name=>"two"}], "Fruit" => [{:type=>"Fruit", :name=>"four"}] }
and then I can't modify it to leave just the name and not the full hash. I need to do this in one line because is for a
grouped_options_for_select
on a Rails form.-
Stefan almost 11 yearsThere's an
option_groups_from_collection_for_select
helper.
-
-
steenslag almost 11 yearsThe last block can be written as
{|_, v| v.map!{|h| h[:name]}}
-
sawa almost 11 years@steenslag Thanks. I forgot about it.
-
Cary Swoveland almost 11 years...or
each_value...
, and don't see why the!
. -
Cary Swoveland almost 11 yearsNice! (But your preamble sounds like a drum roll. :-) )
-
Cary Swoveland almost 11 years
.each_value {|v| v.map!{|h| h[:name]}}
works, but I see!
is needed. -
Cary Swoveland almost 11 yearsYour answer has given me greater insight into the coolness of
inject
. Thanks! -
Matstar over 4 years
transform_values
is now part of Ruby itself (since 2.4, I think).