Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to initialize and update deeply nested Hash

Tags:

ruby

ruby-hash

I have a Hash and I want to insert some data into it at a deep level, but a key might be missing at any level. So, I am conditionally initializing it before updating its value at every level.

What would be a better way to write this or an approach that can make code less ugly?

data[:foo] ||= {}
data[:foo][:bar] ||= {}
data[:foo][:bar][:baz] ||= []
data[:foo][:bar][:baz] << 99
like image 451
Jagdeep Singh Avatar asked May 22 '18 12:05

Jagdeep Singh


People also ask

How do I access nested hash?

Accessing a specific element in a nested hash is very similar to a nested array. It is as simple as calling hash[:x][:y] , where :x is the key of the hash and :y is the key of the nested hash.

What is a nested hash?

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.

How do you merge hashes 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.


1 Answers

Use hash autovivification:

data = Hash.new { |h, k| h[k] = h.dup.clear }
#⇒ {}

# or, credits to @Amadan:
data = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
#⇒ {}

data[:foo][:bar][:baz] = 42
data
#⇒ {:foo=>{:bar=>{:baz=>42}}}

The trick used here is we use Hash#default_proc to create nested keys.

For your case:

(data[:foo][:bar][:baz] = []) << 99
like image 149
Aleksei Matiushkin Avatar answered Sep 29 '22 10:09

Aleksei Matiushkin