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.
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
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
···
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?