# How to implement a hash whose key is another hash?

**URL:** <https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527>\
**Category:** Ruby\
**Created:** [August 20, 2007, 5:35pm UTC](https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527 "2007-08-20T17:35:39Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [August 20, 2007, 5:35pm UTC](https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527/1 "2007-08-20T17:35:39Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [August 20, 2007, 6:24pm UTC](https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527/2 "2007-08-20T18:24:49Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [August 21, 2007, 2:29am UTC](https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527/3 "2007-08-21T02:29:27Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [September 25, 2007, 11:10pm UTC](https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527/4 "2007-09-25T23:10:27Z")

</div>

On 8/20/07, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [September 25, 2007, 11:02pm UTC](https://www.ruby-forum.com/t/how-to-implement-a-hash-whose-key-is-another-hash/112527/5 "2007-09-25T23:02:35Z")

</div>

On Aug 20, 8:58 am, removed\_email\_address@domain.invalid 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.
