3

I'm trying to figure out how i can convert a complex hash like this:

{
  ["A", "B"]=>{"id"=>123,"name"=>"test"},
  ["A", "F"]=>{"id"=>236,"name"=>"another test"},
  ["C", "F"]=>{"id"=>238,"name"=>"anoother test"}
}

into an even more complex hash like

{
  "A"=>{
     "B"=>{"id"=>123,"name"=>"test"},
     "F"=>{"id"=>236,"name"=>"another test"}
  },
  "C"=>{
     "F"=>{"id"=>238,"name"=>"anoother test"}
  }
}

Any help would be really welcome!

2 Answers 2

3

each_with_object could be the rescue:

hash.each_with_object(Hash.new {|h, k| h[k] = {}}) do |((first, last), v), memo|  
  memo[first].merge!(last => v)
end
#=> {"A"=>{"B"=>{"id"=>123, "name"=>"test"}, 
#          "F"=>{"id"=>236, "name"=>"another test"}}, 
#    "C"=>{"F"=>{"id"=>238, "name"=>"anoother test"}}}
Sign up to request clarification or add additional context in comments.

1 Comment

Instead of doing it yourself with Array#{first/last} you can tell Ruby to decompose k: |((k1, k2), v), memo|. Depending on the actual data you can even give it a more fitting name than k2 (or k.last).
3

You can also use Enumerable#group_by then Hash#transform_values by Enumerable#map to a new hash using Array#to_h:

h.group_by { |h,k| h.first }.transform_values { |v| v.map { |a, b| [a.last, b] }.to_h }

1 Comment

Really nice! Great one-liner!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.