using my own objects as hash keys - a question 
Author Message
 using my own objects as hash keys - a question

Hello all,

Could someone explain to me why the following
does not work as I expect:

class MyObject              # will use its objects as hash keys
  def initialize (someAttr)

  end

  def hash

  end

end

key1=MyObject.new('qwerty')
key2=MyObject.new('qwerty')

puts key1.hash == key2.hash #=> true  
# Naturally

hash=Hash.new

hash[key1]=6

puts hash[key1]  #=> 6
# Ok, as expected

puts hash[key2]  #=> nil  
# Why?!!  If key1.hash == key2.hash, why doesn't it work?

# Same question here
puts hash.has_key?(key1) #=> true
puts hash.has_key?(key2) #=> false

Have I missed something ?
I use Ruby 1.6.4

Yuri Leikind



Mon, 01 Mar 2004 21:58:10 GMT  
 using my own objects as hash keys - a question
Quote:
> Could someone explain to me why the following
> does not work as I expect:

<snip>

Quote:
> hash=Hash.new

> hash[key1]=6

> puts hash[key1]  #=> 6
> # Ok, as expected

> puts hash[key2]  #=> nil
> # Why?!!  If key1.hash == key2.hash, why doesn't it work?

> # Same question here
> puts hash.has_key?(key1) #=> true
> puts hash.has_key?(key2) #=> false

> Have I missed something ?

Well, yes, I guess you've missed how hash tables work. A hash table is
usually described as a collection of "buckets", one for each hash value.
Whenever you add a new key to a hash table, the code will compute the hash
value for that key, find the corresponding bucket for that hash value, and
place a reference to the key in that bucket. When you look up that key in
the hash table (e.g. by calling has_key?) the code once again computes the
hash code for the key, looks in the corresponding bucket -- which may now
have several different keys, all with the same hash value -- and looks for
the requested key.

So even though key1 and key2 have the same hash code (6), you've only put
key1 in the hash table, and it's still a different instance than key2. If
you were to also add key2 to the hash table, they would both end up in the
same "bucket" and the hash table would include both keys.



Mon, 01 Mar 2004 23:02:21 GMT  
 using my own objects as hash keys - a question

Quote:

> > Could someone explain to me why the following
> > does not work as I expect:

> <snip>

> > hash=Hash.new

> > hash[key1]=6

> > puts hash[key1]  #=> 6
> > # Ok, as expected

> > puts hash[key2]  #=> nil
> > # Why?!!  If key1.hash == key2.hash, why doesn't it work?

> > # Same question here
> > puts hash.has_key?(key1) #=> true
> > puts hash.has_key?(key2) #=> false

> > Have I missed something ?

> Well, yes, I guess you've missed how hash tables work. A hash table is
> usually described as a collection of "buckets", one for each hash value.
> Whenever you add a new key to a hash table, the code will compute the hash
> value for that key, find the corresponding bucket for that hash value, and
> place a reference to the key in that bucket. When you look up that key in
> the hash table (e.g. by calling has_key?) the code once again computes the
> hash code for the key, looks in the corresponding bucket -- which may now
> have several different keys, all with the same hash value -- and looks for
> the requested key.

> So even though key1 and key2 have the same hash code (6), you've only put
> key1 in the hash table, and it's still a different instance than key2. If
> you were to also add key2 to the hash table, they would both end up in the
> same "bucket" and the hash table would include both keys.

I got it. Thank you.

Yuri Leikind



Tue, 02 Mar 2004 01:03:29 GMT  
 using my own objects as hash keys - a question

Y> Have I missed something ?

 Yes, when you want to re-define #hash you must also redefine #eql?

 You have at http://www.ruby-lang.org/en/man-1.4/Object.html#hash

    Returns the integer hash value of the object. It is used in the Hash
    class to calculate the holding place of an object. The hash value of
    two objects must be equal, where these two objects are equal by using
    eql? operator. So, whenever you redefine the definition of the eql?
    operator in any class, don't forget to redefine hash method according
    to the definition.  

 For example :

pigeon% cat b.rb
#!/usr/bin/ruby
class MyObject
   attr_reader :someAttr
   def initialize (someAttr)

   end

   def eql? other
      other.kind_of?(self.class) && someAttr == other.someAttr
   end

   def hash

   end
end

key1=MyObject.new('qwerty')
key2=MyObject.new('qwerty')

puts key1.hash == key2.hash #=> true  

hash=Hash.new

hash[key1]=6

puts hash[key1]  #=> 6

puts hash[key2]  #=> nil  

puts hash.has_key?(key1) #=> true
puts hash.has_key?(key2) #=> false
pigeon%

pigeon% b.rb
true
6
6
true
true
pigeon%

--

Guy Decoux



Mon, 01 Mar 2004 23:51:18 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. hash as key in hash

2. Hash.new(Hash.new) doesn't use Hash.new as default value

3. Using the Plus key as a tab key.

4. Memo field, using enter key and tab key.

5. CW2001.01 Search for number key using GET(file,key) PROBLEM

6. Using ENTER-key as TAB-key

7. C4 Newbie Question - Using Functions Keys

8. Accessing hash values sorted by their keys

9. sort the hash keys

10. Checking hash key's and values, with case insensitivity

11. Primary Key Hash help

12. valid hash keys

 

 
Powered by phpBB® Forum Software