Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting a nested hash into a flat hash

Tags:

ruby

hash

This question is the inverse of this question.

Given a nested hash like

{     :a => {        :b => {:c => 1, :d => 2},        :e => 3,     },     :f => 4, } 

what is the best way to convert it into a flat hash like

{     [:a, :b, :c] => 1,     [:a, :b, :d] => 2,     [:a, :e] => 3,     [:f] => 4, } 
like image 599
sawa Avatar asked Mar 10 '12 16:03

sawa


2 Answers

Another way:

def flat_hash(h,f=[],g={})   return g.update({ f=>h }) unless h.is_a? Hash   h.each { |k,r| flat_hash(r,f+[k],g) }   g end  h = { :a => { :b => { :c => 1,                       :d => 2 },               :e => 3 },       :f => 4 }  flat_hash(h) #=> {[:a, :b, :c]=>1, [:a, :b, :d]=>2, [:a, :e]=>3, [:f]=>4} 
like image 194
Cary Swoveland Avatar answered Sep 22 '22 03:09

Cary Swoveland


Very similar to Adiel Mittmann's solution

def flat_hash(h, k = [])   new_hash = {}   h.each_pair do |key, val|     if val.is_a?(Hash)       new_hash.merge!(flat_hash(val, k + [key]))     else       new_hash[k + [key]] = val     end   end   new_hash end 

Edit: Refactored for elegance. Should be almost as fast.

def flat_hash(hash, k = [])   return {k => hash} unless hash.is_a?(Hash)   hash.inject({}){ |h, v| h.merge! flat_hash(v[-1], k + [v[0]]) } end 
like image 36
Kyle Avatar answered Sep 24 '22 03:09

Kyle