Reputation: 2762
Situation:
I have an array of objects. Each object has a name, and ID, and another attribute. I want to map this in to an array of hashes that have the name
, an array of id
s, and the other attribute (same per name).
So I have something like:
[{:name=>"Hello", :id=>1}, {:name=>"Hello", :id=>2}, {:name=>"Bye", :id=>3}]
I want it to look like
[{:name=>"Bye", :ids=>[3]}, {:name=>"Hello", :ids=>[1, 2]}]
I have tried using chunk, but I'm unable to properly figure out how to use it without it being a massive pile of poorly-cooked spaghetti.
Right now I have managed to cleanly sort (at the beginning), and I can map it fine, but I feel like further iterating over it is needlessly wasteful, and I should group or chunk them beforehand.
Without the chunking, my code looks like this:
list_of_designers.sort!{ |x,y| I18n.transliterate(x.name).upcase <=> I18n.transliterate(y.name).upcase }
list_of_designers.map do |designer|
{
name: designer.name,
designer_ids: [designer.id]
}
end
However, this leaves me with siblings (i.e., designers with the same name, but different IDs). How can I cleanly collapse these siblings?
Upvotes: 2
Views: 912
Reputation: 10898
Try this:
original = [{:name=>"Hello", :id=>1}, {:name=>"Hello", :id=>2}, {:name=>"Bye", :id=>3}]
modified = original.map { |i| i[:name] }.uniq.map { |name| {name: name, ids: ary.find_all { |i| i[:name] == name }.map { |i| i[:id] } } }
# => [{:name=>"Hello", :ids=>[1, 2]}, {:name=>"Bye", :ids=>[3]}]
Upvotes: 0
Reputation: 118289
I would do as below :
a = [{:name=>"Hello", :id=>1}, {:name=>"Hello", :id=>2}, {:name=>"Bye", :id=>3}]
a.group_by{|h| h[:name] }.map{|k,v| {:name => k, :ids => v.map{|h| h[:id]}}}
# => [{:name=>"Hello", :ids=>[1, 2]}, {:name=>"Bye", :ids=>[3]}]
Upvotes: 2