This question is the inverse of this question.
Given a hash that has an array for each key like
{
[:a, :b, :c] => 1,
[:a, :b, :d] => 2,
For a mixed hash/array nested structure you can use this. (Modified for arrays as well)
def unflatten(h={})
ret = {}
h.each do |k,v|
node = ret
keys = k.split('.').collect { |x| x.to_i.to_s == x ? x.to_i : x }
keys.each_cons(2) do |x, next_d|
if(next_d.is_a? Fixnum)
node[x] ||= []
node=node[x]
else
node[x] ||={}
node=node[x]
end
end
node[keys[-1]] = v
end
ret
end
provided you used the below for flattening. ( dot separate string for key instead of array [split on . if you need] )
def flatten_hash(hash)
hash.each_with_object({}) do |(k, v), h|
if v.is_a? Hash
flatten_hash(v).map do |h_k, h_v|
h["#{k}.#{h_k}"] = h_v
end
elsif v.is_a? Array
flatten_array(v).map do |h_k,h_v|
h["#{k}.#{h_k}"] = h_v
end
else
h[k] = v
end
end
end
def flatten_array(array)
array.each_with_object({}).with_index do |(v,h),i|
pp v,h,i
if v.is_a? Hash
flatten_hash(v).map do |h_k, h_v|
h["#{i}.#{h_k}"] = h_v
end
elsif v.is_a? Array
flatten_array(v).map do |h_k,h_v|
h["#{i}.#{h_k}"] = h_v
end
end
end
end