I want to "flatten" (not in the classical sense of .flatten
) down a hash with varying levels of depth, like this:
{ :foo => "bar", :hello => { :world => "Hello World", :bro => "What's up dude?", }, :a => { :b => { :c => "d" } } }
down into a hash with one single level, and all the nested keys merged into one string, so it would become this:
{ :foo => "bar", :"hello.world" => "Hello World", :"hello.bro" => "What's up dude?", :"a.b.c" => "d" }
but I can't think of a good way to do it. It's a bit like the deep_
helper functions that Rails adds to Hashes, but not quite the same. I know recursion would be the way to go here, but I've never written a recursive function in Ruby.
We can merge two hashes using the merge() method. When using the merge() method: Each new entry is added to the end. Each duplicate-key entry's value overwrites the previous value.
The flatten() is an inbuilt method in Ruby returns a new set that is a copy of the set, flattening each containing set recursively. Parameters: The function does not takes any parameter. Return Value: It returns a boolean value. It returns true if the set is empty or it returns false.
Nested hashes allow us to further group, or associate, the data we are working with. They help us to deal with situations in which a category or piece of data is associated not just to one discrete value, but to a collection of values.
You could do this:
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}".to_sym] = h_v end else h[k] = v end end end flatten_hash(:foo => "bar", :hello => { :world => "Hello World", :bro => "What's up dude?", }, :a => { :b => { :c => "d" } }) # => {:foo=>"bar", # => :"hello.world"=>"Hello World", # => :"hello.bro"=>"What's up dude?", # => :"a.b.c"=>"d"}
Because I love Enumerable#reduce
and hate lines apparently:
def flatten_hash(param, prefix=nil) param.each_pair.reduce({}) do |a, (k, v)| v.is_a?(Hash) ? a.merge(flatten_hash(v, "#{prefix}#{k}.")) : a.merge("#{prefix}#{k}".to_sym => v) end end
irb(main):118:0> flatten_hash(hash) => {:foo=>"bar", :"hello.world"=>"Hello World", :"hello.bro"=>"What's up dude?", :"a.b.c"=>"d"}
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