Max
Max

Reputation: 1556

ruby nested hash

i just had a quick question, consider this piece of code:

class Hash
  def value_for(keys, value)
    common = self
    while keys.size > 1 and !common.nil?
      common = common[keys.shift] || { }
    end
    common[keys.last] = value
  end
end

With this piece of code i hope to be able to create a nested hash, by passing an array of the nested nodes and a value it should be assigned.

It should work like the following:

hash = {
  "message" => "hello world"
}

hash.value_for [ "nested", "message" ], "hello world"

hash
#=> {
       "message" => "hello world",
       "nested" => {
         "message" => "hello world"
       }
    }

hash.value_for [ "second", "nested", "message" ], "hello world"

hash
#=> {
       "message" => "hello world",
       "nested" => {
         "message" => "hello world"
       },
       "second" => {
         "nested" => {
           "message" => "hello world"
         }
       }
    }

for some reason my code doesn't work when creating a new hash. I suspect it has something to do with common = common[keys.shift] || { }

Can someone help me please? I have the feeling i am missing something stupid....

Thanks a lot

Upvotes: 0

Views: 503

Answers (2)

sawa
sawa

Reputation: 168101

You can do it like this:

class Hash
  def value_for((*keys, last), value)
    _h = nil
    keys.inject(self){|h, k| _h = h[k] ||= {}}
    _h[last] = value
  end
end

Upvotes: 1

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 70929

Here is a working code sample:

class Hash
  def value_for(keys, value)
    common = {}
    common[keys.last] = value
    (keys.size - 2).downto(0).each do |index|
      common[keys[index]] = {keys[index+1] => common[keys[index+1]]}
    end 
    return common
  end 
end

The problems with your code are:

  1. To achieve what you try to do you need to traverse keys in reverse order, because key[i] depends on the value for key[i+1]
  2. You need to create a new hash for each key, while common[keys.shift] is actually a value, you should add another level of nesting.

Hope this helps.

Upvotes: 0

Related Questions