Forum: Ruby Array in a Hash

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Damaris F. (Guest)
on 2008-12-05 17:32
Hi you all,

I have the following code,where I have a hash whose entries are
initalized by an empty Array:

h = Hash.new(Array.new(0))
h["a"] << 0
h["b"] << 6
h["a"] << 5
h["b"] << 10
p h["a"]
p h["b"]

Both "p" prints the same: [0,6,5,10]
What am I doing wrong? (I want h["a"] to be [0,5] and h["b"]=[6,10]
James G. (Guest)
on 2008-12-05 17:42
(Received via mailing list)
On Dec 5, 2008, at 9:26 AM, Damaris F. wrote:

> I have the following code,where I have a hash whose entries are
> initalized by an empty Array:
>
> h = Hash.new(Array.new(0))

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

> h["a"] << 0
> h["b"] << 6
> h["a"] << 5
> h["b"] << 10
> p h["a"]
> p h["b"]
>
> Both "p" prints the same: [0,6,5,10]
> What am I doing wrong? (I want h["a"] to be [0,5] and h["b"]=[6,10]

If you just pass an object to Hash.new() the exact same object is used
to initialize all entries.  That's okay with something like a Fixnum
which will have to be replaced, but not intended with a mutable object
like Array.  Switching to the block form as I did above forces Ruby to
run the code each time, getting us a new Array.

James Edward G. II
Michael L. (Guest)
on 2008-12-05 17:48
(Received via mailing list)
On Fri, Dec 5, 2008 at 9:26 AM, Damaris F.
<removed_email_address@domain.invalid> wrote:
> p h["a"]
> p h["b"]
>
> Both "p" prints the same: [0,6,5,10]
> What am I doing wrong? (I want h["a"] to be [0,5] and h["b"]=[6,10]

That form of Hash.new does not create a different new Array for each
new hash key, it creates a single Array instance to which all new hash
keys refer. You might prefer the block form of Hash.new.

irb(main):001:0> h = Hash.new(Array.new(0))
=> {}
irb(main):002:0> h[:a] << 0
=> [0]
irb(main):003:0> h[:b] << 1
=> [0, 1]
irb(main):004:0> h[:a].object_id
=> 1073560370
irb(main):005:0> h[:b].object_id
=> 1073560370
irb(main):006:0> g = Hash.new{|hash, key| hash[key] = Array.new(0)}
=> {}
irb(main):007:0> g[:a] << 0
=> [0]
irb(main):008:0> g[:b] << 1
=> [1]
irb(main):009:0> g[:a].object_id
=> 1073475250
irb(main):010:0> g[:b].object_id
=> 1073464620
irb(main):011:0> g[:a] << 4
=> [0, 4]
irb(main):012:0> g[:b] << 5
=> [1, 5]

-Michael C. Libby
This topic is locked and can not be replied to.