Dennis
Dennis

Reputation: 1975

How to get specific keys in Array of Hashes?

I have an array of Hashes:

[{"folder"=>"j"}, {"path"=>"p"}, {"folder"=>"b"}]

I merge them via:

flat_map(&:entries)
  .group_by(&:first)
  .map{|k,v| Hash[k, v.map(&:last)]}

Then I get:

[{"folder"=>["j", "b"]}, {"path"=>["p"]}]

as expected.

My question is, :folder and :path (I will also have more keys) can be randomly ordered. Instead of looping and checking for key names, Is it possible to get each hash separately? For example;

# After merging...
folders = elem[:folder] # => ["j", "b"]
paths =  elem[:path].. # => ["p"]

Basically I would like to get :folder and :path without looping all the time.

Upvotes: 0

Views: 234

Answers (3)

steenslag
steenslag

Reputation: 80105

ar =[{"folder"=>"j"}, {"path"=>"p"}, {"folder"=>"b"}]
elem = Hash.new{[]}

ar.each{|hash| hash.each{|k,v| elem[k] <<= v }}
folders, paths = elem.values_at("folder", "path")

Upvotes: 2

potashin
potashin

Reputation: 44601

You could use a different approach in the first place:

collection = [{"folder"=>"j"}, {"path"=>"p"}, {"folder"=>"b"}]

Using each_with_object (or a similar approach with reduce):

collection.each_with_object({}) do |values, s|
  values.each do |key, value|
    (s[key.to_sym] ||= []) << value
  end
end

Demonstration

or group_by and transform_values:

collection.
  group_by { |item| item.first.first.to_sym  }.
  transform_values { |values| values.flat_map(&:values) }

Upvotes: 2

Pedro Adame Vergara
Pedro Adame Vergara

Reputation: 592

You can solve your problem by this:

elem = [{"folder"=>["j", "b"]}, {"path"=>["p"]}]
merged = elem.reduce({}, :merge)
# => {"folder" => ["j", "b"], "path" => ["p"]}
merged["folder"]
# => ["j", "b"]
merged["path"]
# => ["p"]

Upvotes: 2

Related Questions