Hash of arrays - whats going on?

S

stephen O'D

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

Kyle Schmitt

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
 
B

Ben Bleything

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
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top