10

I have a piece of code like this:

my_hash = {}
first_key = 1
second_key = 2
third_key = 3
my_hash[first_key][second_key][third_key] = 100

and the ruby interpreter gave me an error says that:

undefined method `[]' for nil:NilClass (NoMethodError)

So does it mean I cannot use hash like that? or do you think this error might because of something else?

2
  • Hints on how to debug your code: stackoverflow.com/q/3955688/38765 Commented May 1, 2012 at 2:10
  • Allan, you should probably accept one of the answers, unless you consider that your question wasn't fully answered. (Probably either texasbruce's or mine, since we told you a way to achieve what you want. Though I repeat that it's not necessarily good style.) Commented May 2, 2012 at 9:24

4 Answers 4

12

Hashes aren't nested by default. As my_hash[first_key] is not set to anything, it is nil. And nil is not a hash, so trying to access one of its elements fails.

So:

my_hash = {}
first_key = 1
second_key = 2
third_key = 3

my_hash[first_key] # nil
my_hash[first_key][second_key]
# undefined method `[]' for nil:NilClass (NoMethodError)

my_hash[first_key] = {}
my_hash[first_key][second_key] # nil

my_hash[first_key][second_key] = {}

my_hash[first_key][second_key][third_key] = 100
my_hash[first_key][second_key][third_key] # 100
Sign up to request clarification or add additional context in comments.

2 Comments

hello thank you, but actually I made my hash to be static (@@my_hash), so will the sub hashes be static as well? So the sub_hashes will not be initialized again if I put this piece of code in a loop?
@AllanJiang There's no such thing as "static" in Ruby.
8

The way you are using hash is not valid in Ruby, because every single value has to be assigned to a hash first before going to nested hash(I suppose you were from PHP?), but you can use vivified hash:

my_hash = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)}
first_key = 1
second_key = 2
third_key = 3
my_hash[first_key][second_key][third_key] = 100
p my_hash

#output: {1=>{2=>{3=>100}}}

This is the way you might be comfortable with.

Comments

2

You can't use hashes like that; my_hash[first_key] is just nil, and then the next indexing operation fails. It's possible to make a hash object that behaves in the way you're looking for -- see http://t-a-w.blogspot.co.uk/2006/07/autovivification-in-ruby.html -- but it's not clear that this is good style.

Comments

0

You can do something like

class NilClass

  def [] key
    nil
  end

end

in the initializers like nil_overrides.rb and you will able to use nil['xxx'].

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.