Something wrong with my hash of hash

L

Lars Ticot

I try to get a hash of hash to make some sort of counter (I have a set
of random pair and want to count the number of times they appear). I use
this code but even if I can access data, my hash seems empty (so each
and the others don't work):


h = Hash.new(Hash.new(0))
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
p h["a"]["b"] => 2
p h["a"]["c"] => 1
p h.class => Hash
p h["a"].class => Hash
p h["a"]["b"].class => Fixnum
p h => {}


What's wrong?

Lars
 
L

Lars Ticot

Changing declaration by

h = Hash.new {|h,k| h[k] = Hash.new(0) }

makes things ok. What are the difference beetween the two declaration?

Lars
 
G

Gennady Bystritsky

I try to get a hash of hash to make some sort of counter (I have a set
of random pair and want to count the number of times they
appear). I use
this code but even if I can access data, my hash seems empty (so each
and the others don't work):


h =3D Hash.new(Hash.new(0))
h["a"]["b"] +=3D 1
h["a"]["b"] +=3D 1
h["a"]["c"] +=3D 1
p h["a"]["b"] =3D> 2
p h["a"]["c"] =3D> 1
p h.class =3D> Hash
p h["a"].class =3D> Hash
p h["a"]["b"].class =3D> Fixnum
p h =3D> {}


What's wrong?

Lars

Try this definition:

h =3D Hash.new { |h, k|
h[k] =3D Hash.new(0)
}

It will actually modify 'h' rather than simply returning and modifying the =
default value.

Gennady.
 
R

Rick DeNatale

I try to get a hash of hash to make some sort of counter (I have a set
of random pair and want to count the number of times they appear). I use
this code but even if I can access data, my hash seems empty (so each
and the others don't work):


h = Hash.new(Hash.new(0))
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
p h["a"]["b"] => 2
p h["a"]["c"] => 1
p h.class => Hash
p h["a"].class => Hash
p h["a"]["b"].class => Fixnum
p h => {}


What's wrong?

You're using the wrong form of Hash.new for this use case.

Hash.new(default)

gives you a hash which simply returns default from [key] when key
doesn't exist, it leaves the hash itself alone.

You need to use a block

h = Hash.new {|h, k| h[k] = Hash.new(0)}
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
h["a"]["b"] # => 2
h["a"]["c"] # => 1
h.class # => Hash
h # => {"a"=>{"b"=>2, "c"=>1}}
 
S

Sebastian Hungerecker

Lars said:
h = Hash.new(Hash.new(0))
Changing declaration by
h = Hash.new {|h,k| h[k] = Hash.new(0) }
makes things ok. What are the difference beetween the two declaration?

There are two differences:
First: The first version executes "Hash.new(0)" once (before the outer
Hash.new is called, since parameters are evaluated before the actual method
call (obviously)) and stores the result as the default value. This means that
if you do something like h[:foo][:chunky] = "bacon" and h[:foo] has not been
assigned before, you will actually change the default value, so h[:bar]
[:chunky] will also be "bacon". The second version just stores the block and
executes it everytime a key that hasn't been assigned before is accessed.

Second: The second version has "h[k] =" in it, so it will not only return the
newly created hash, it will also store it in the outer hash. The first
version won't do that, which means that h will always appear as empty until
you do any actual assignments to it.


HTH,
Sebastian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

My Status, Ciphertext 2
Hash Reverse ? 8
hash of hash? 6
Array in a Hash 2
Help with my responsive home page 2
calendar hash 0
tricky hash initialization 5
Dont work, it´s something whit the loops? 1

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,200
Latest member
LaraHunley

Latest Threads

Top