Is there a simpler permutation of the next hash? I have a solution that works, but the transpose method is hard to read. A use case is a hash of tasks (j1, j2, j3, etc.) and the dates on which they occur (d1, d2, d3, etc.). The requirement is to accept a hash of events (e1, e2, e3, etc.) that are grouped by date, then by task, and transpose them to events grouped by task, and then by date .
I experimented with the #zip method, but for this you will need to enter nil in j1: d1, and then remove them from the results. I also tried to find an example of using #zip with a block argument. I understand that #zip with a block always returns zero , but as a result, I could not figure out how you ever used it.
require 'rspec' require 'pry' # | d1 | d2 | d3 | # ---------------------- # j1 | | e2 | e3 | # -------------------------- # j2 | e4 | e5 | e6 | # -------------------------- # j3 | e7 | | e9 | # -------------------------- def transpose(h) Hash[ dates(h).map do |d| [ d, Hash[ h.keys.map do |j| h[j][d] ? [j, h[j][d]] : nil end.compact ] ] end ] end def dates(h) h.values.map(&:keys).reduce(:|).sort end describe "transpose" do let(:starting) { { j1: { d2: :e2, d3: :e3 }, j2: { d1: :e4, d2: :e5, d3: :e6 }, j3: { d1: :e7, d3: :e9 } } } let(:transposed) { { d1: { j2: :e4, j3: :e7 }, d2: { j1: :e2, j2: :e5 }, d3: { j1: :e3, j2: :e6, j3: :e9 } } } it { expect(dates(starting)).to eq([:d1, :d2, :d3]) } it { expect(transpose(starting)).to eq(transposed) } end