# Hash of arrays - whats going on?

**URL:** <https://www.ruby-forum.com/t/hash-of-arrays-whats-going-on/109893>\
**Category:** Ruby\
**Created:** [July 19, 2007, 11:53pm UTC](https://www.ruby-forum.com/t/hash-of-arrays-whats-going-on/109893 "2007-07-19T23:53:09Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![stephen\_OSD](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df788c/32.png) [@stephen\_OSD](https://www.ruby-forum.com/u/stephen_OSD)\
**Post date:** [July 19, 2007, 11:53pm UTC](https://www.ruby-forum.com/t/hash-of-arrays-whats-going-on/109893/1 "2007-07-19T23:53:09Z")

</div>

I want a hash, where the values of the keys are arrays, eg

h = Hash.new  
h.default = []

h[‘foo’] \<\< 10  
h[foo’] \<\< 20  
h[‘bar’] \<\< 23  
h[‘bar’] \<\< 33

I thought this would give me

{ ‘foo’ =\> [20 30],  
‘bar’ =\> [23, 33] }

but it doesn’t - it seems to put the same array in the value of each  
key. Some googling revealed I need to create my hash like:

h = Hash.new { |hash, key| hash[key] = [] }

So my problem is solved, but why do you have to do it like this? At  
the risk of answering my own question, is it because the block is re-  
executed everytime you access a non existent key, creating a brand new  
array object, while the first way, it just initialises the value to  
the same array each time?

Thanks,

Stephen.

---

<div class="post-metadata">

**Author:** ![stephen\_OSD](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df788c/32.png) [@stephen\_OSD](https://www.ruby-forum.com/u/stephen_OSD)\
**Post date:** [July 20, 2007, 12:54am UTC](https://www.ruby-forum.com/t/hash-of-arrays-whats-going-on/109893/2 "2007-07-20T00:54:15Z")

</div>

On Fri, Jul 20, 2007, stephen O’D wrote:

> So my problem is solved, but why do you have to do it like this? At  
> the risk of answering my own question, is it because the block is re-  
> executed everytime you access a non existent key, creating a brand new  
> array object, while the first way, it just initialises the value to  
> the same array each time?

The default value you provide is a reference… in this case, you say  
“use this array as the default value”, not “use an empty array as a  
default value”. To see what I mean, try this:

```
empty_ary = []
h = Hash.new
h.default = empty_ary

h['foo'] << 10
puts empty_ary.size

h[foo'] << 20
puts empty_ary.size

h['bar'] << 23
puts empty_ary.size

h['bar'] << 33
puts empty_ary.size

```

That should show you what’s happening.

Ben

---

<div class="post-metadata">

**Author:** ![stephen\_OSD](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/df788c/32.png) [@stephen\_OSD](https://www.ruby-forum.com/u/stephen_OSD)\
**Post date:** [July 20, 2007, 12:56am UTC](https://www.ruby-forum.com/t/hash-of-arrays-whats-going-on/109893/3 "2007-07-20T00:56:15Z")

</div>

default just lets you return a default value if the request key  
doesn’t exist, it’s not _supposed_ to change the state of the hash.

What was happening is an array was presented to you when you called  
h[‘foo’], and you were putting a value in it, but the array was never  
saved to a variable, so it went away.

With the original code try the following code, it may help you  
understand:  
h[‘foo’] \<\< 10  
puts h.length  
h[foo’] \<\< 20  
puts h.length
