I have an array like this:
[{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}, {:a=>"2017-01-02", :b=>"5", :c=>"1"}]
If, for example, I group the array with the key ":a", the result is:
p = y.group_by { |g| g[:a]}
=> {"2017-01-01"=>[{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}], "2017-01-02"=>[{:a=>"2017-01-02", :b=>"5", :c=>"1"}]}
Now I want to group for each ":a" the key ":b" like:
=> {"2017-01-01"=>["2" => [{:a => "2017-01-01", :b => "2", :c => "1" }], ... }
How can I do? Thanks in advance.
Edit:
multiple group by ... 1° group_by a, 2° group_by b the result of 1°, etc..
y.group_by {|g| g[:a]}.map do |k,v|
[
k, v.group_by { |d| d[:b] }.map do |p,q|
[p, q.group_by { |f| f[:c] }]
end.to_h
]
end.to_h
Quick answer, using your code above:
y = [{:a=>"2017-01-01", :b=>"2", :c=>"1"}, {:a=>"2017-01-01", :b=>"2", :c=>"2"}, {:a=>"2017-01-02", :b=>"5", :c=>"1"}]
p = y.group_by { |g| g[:a]}
q = p.map {|date, list| [date, list.group_by {|g| g[:b]}]}.to_h
This gives the desired result of:
q == {
"2017-01-01" => {
"2"=> [
{:a=>"2017-01-01", :b=>"2", :c=>"1"},
{:a=>"2017-01-01", :b=>"2", :c=>"2"}
]
},
"2017-01-02" => {
"5"=> [
{:a=>"2017-01-02", :b=>"5", :c=>"1"}
]
}
}
This slightly odd pattern of mapping the hash to a list of arrays, then converting it back to a hash (using to_h
) can be simplified slightly if you are working with a Rails v4.2+ project, by use of Hash#transform_values
:
p.transform_values {|list| list.group_by {|g| g[:b]}}
However with that said, it is generally considered bad practice to be manipulating complex, nested hash objects like this. If your code gets too complicated, you may wish to consider redesigning how it works, in a more Object-Oriented manner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With