How to implement a hash whose key is another hash?

I understand that the key of a hash can be any object. Therefore,
I would think that the key of a hash can be another hash. If I have
the following code sequence. (I using ruby 1.8.5 (2006-08-25) [i486- linux])

require ‘pp’
test ={}
test[“new”=>“girl”]= 100
test[“new”=>“girl”]= 200
pp test

I am expecting the output to be

{{“new”=>“girl”}=>200}

However the output I am getting is

{{“new”=>“girl”}=>100,
{“new”=>“girl”}=>200}

Could some explain how to use hash key which is of type hash

unknown wrote:

Could some explain how to use hash key which is of type hash

Perhaps studying this will explain your confusion.

require ‘pp’
test ={}
k1 = {“new”=>“girl”}
k2 = {“new”=>“girl”}
test[k1]= 100
test[k2]= 200
pp k1.eql?(k2)
pp test
test ={}
test[k1]= 100
test[k1]= 200
pp test

Note that each instance of “new”=>“girl”
is a different hash object. Basing the
key on a hash does not look like a good
idea in general. Consider what happens
when you extend k1.

k1 = {“new”=>“girl”}
test ={}
k1[“bad”]=“idea”
test[k1]= 100
k1[“bad”]=“idea”
test[k1]= 200
pp test

Keys should be stable objects.

Ian W.

unknown wrote:

I understand that the key of a hash can be any object. Therefore,
I would think that the key of a hash can be another hash. If I have
the following code sequence. (I using ruby 1.8.5 (2006-08-25) [i486- linux])

require ‘pp’
test ={}
test[“new”=>“girl”]= 100
test[“new”=>“girl”]= 200
pp test

I am expecting the output to be

{{“new”=>“girl”}=>200}

However the output I am getting is

{{“new”=>“girl”}=>100,
{“new”=>“girl”}=>200}

Could some explain how to use hash key which is of type hash

It’s a bad idea to do what you are doing. However, if you really want
to, you could try installing CICPHash (sudo gem install cicphash). It’s
designed to be a case insensitive hash, but it can easily be generalized
to consider arbitrary sets of keys as equal.

The default implementation will do what you want for this simple case:

irb(main):001:0> require ‘pp’
=> true
irb(main):002:0> require ‘cicphash’
=> true
irb(main):003:0> test = CICPHash.new
=> {}
irb(main):004:0> test[“new”=>“girl”]= 100
=> 100
irb(main):005:0> test[“new”=>“girl”]= 200
=> 200
irb(main):006:0> pp test
{{“new”=>“girl”}=>200}
=> nil

However, the default implementation won’t necessarily work for hashes
with multiple keys, as the order of the keys in the hash is undefined.
You can change that by redefining the CICPHash#convert_key method.

However, as previously mentioned, you probably shouldn’t use hashes as
hash keys.

Jeremy

On 8/20/07, [email protected] [email protected] wrote:

pp test

I am expecting the output to be

{{“new”=>“girl”}=>200}

However the output I am getting is

{{“new”=>“girl”}=>100,
{“new”=>“girl”}=>200}

The problem is that you are not using the same key …

k = {‘new’ => ‘girl’}
k.hash #=> 1072992710

h = {}
h[k] = 100
h[k] = 200
p h #=> {{“new” => “girl”} => 200}

k = {‘new’ => ‘girl’}
k.hash #=> 1072934850

h[k] = 300
p h #=> {{“new”=>“girl”}=>300, {“new”=>“girl”}=>200}

To use an object as a hash key, you need to implement a “hash” method
that returns the same value when the contents of the hash are the
same. But this gets tricky.

Blessings,
TwP

On Aug 20, 8:58 am, [email protected] wrote:

I am expecting the output to be

{{“new”=>“girl”}=>200}

However the output I am getting is

{{“new”=>“girl”}=>100,
{“new”=>“girl”}=>200}

Could some explain how to use hash key which is of type hash

irb(main):001:0> h1 = {}
=> {}
irb(main):002:0> h2 = { :foo=>‘bar’ }
=> {:foo=>“bar”}
irb(main):003:0> h1[ h2 ] = ‘hello’
=> “hello”
irb(main):004:0> h1[ h2 ] = ‘world’
=> “world”
irb(main):005:0> h1
=> {{:foo=>“bar”}=>“world”}
irb(main):006:0> h1[ :a=>1 ] = 42
=> 42
irb(main):007:0> h1[ :a=>1 ] = 2000
=> 2000
irb(main):008:0> h1
=> {{:a=>1}=>2000, {:foo=>“bar”}=>“world”, {:a=>1}=>42}

If it’s TRULY the same hash, you get what you expected: the new value
overwrites the old.

What you did, and what you see on lines 6 and 7 above, is to create a
new hash on the fly that happens to have the same values as another
hash. To Ruby, those are treated as two different keys.