# Something wrong with my hash of hash

**URL:** <https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636>\
**Category:** Ruby\
**Created:** [October 29, 2007, 5:54pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636 "2007-10-29T17:54:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![larstico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/4af34b/32.png) [@larstico](https://www.ruby-forum.com/u/larstico)\
**Post date:** [October 29, 2007, 5:54pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636/1 "2007-10-29T17:54:56Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![larstico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/4af34b/32.png) [@larstico](https://www.ruby-forum.com/u/larstico)\
**Post date:** [October 29, 2007, 6:02pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636/2 "2007-10-29T18:02:17Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![larstico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/4af34b/32.png) [@larstico](https://www.ruby-forum.com/u/larstico)\
**Post date:** [October 29, 2007, 6:08pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636/3 "2007-10-29T18:08:27Z")

</div>

removed\_email\_address@domain.invalid wrote:

> h[“a”][“c”] += 1  
> Lars  
> Try this definition:

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

It will actually modify ‘h’ rather than simply returning and modifying  
the default value.

Gennady.

---

<div class="post-metadata">

**Author:** ![larstico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/4af34b/32.png) [@larstico](https://www.ruby-forum.com/u/larstico)\
**Post date:** [October 29, 2007, 6:17pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636/4 "2007-10-29T18:17:49Z")

</div>

On 10/29/07, Lars T. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 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}}

Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![larstico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/4af34b/32.png) [@larstico](https://www.ruby-forum.com/u/larstico)\
**Post date:** [October 29, 2007, 7:26pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636/5 "2007-10-29T19:26:17Z")

</div>

Lars T. wrote:

> > 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

---

<div class="post-metadata">

**Author:** ![larstico](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/4af34b/32.png) [@larstico](https://www.ruby-forum.com/u/larstico)\
**Post date:** [October 29, 2007, 10:50pm UTC](https://www.ruby-forum.com/t/something-wrong-with-my-hash-of-hash/118636/6 "2007-10-29T22:50:38Z")

</div>

Sebastian H. wrote:

> There are two differences:  
> […]

Thanks all of you guys and especially Sebastian for the explanations.

Lars
