Hash return is not correct

class Router
attr_accessor :make, :model
def initialize(make, model)
@make = make
@model = model
end

def ==(other)
return false unless other.is_a?(Router)
make == other.make && model == other.model
end

end

frequency = Hash.new(0)
models = %w(2000 3000 2000 3200)
models.each{|m| frequency[Router.new(‘Linksys’,m)] += 1}
puts frequency[Car.new(‘Linksys’,‘2000’)]

puts should be ‘2’ but I am getting ‘zero’

No the output is correct. Your mistake is assuming that Router.new will
return the same object for the same input parameters. For example:

frequency = Hash.new(0)
models = %w(2000 3000 2000 3200)
models.each{|m| frequency[Router.new(‘Linksys’,m)] += 1}

p frequency => {

#<Router:0x10f80ae70 @model=“3000”, @make=“Linksys”>=>1,

#<Router:0x10f80ae20 @model=“2000”, @make=“Linksys”>=>1,

#<Router:0x10f80aec0 @model=“2000”, @make=“Linksys”>=>1,

#<Router:0x10f80add0 @model=“3200”, @make=“Linksys”>=>1

}

Note each entry is a different object. This is the normal and
correct behaviour. When you do:

puts frequency[Router.new(‘Linksys’,‘2000’)]

I assume you meant this and not Car.new it creates yet another object
which
of course is not in the hash and so returns 0.

On Mon, May 6, 2013 at 9:19 AM, Peter H.
[email protected] wrote:

#<Router:0x10f80ae70 @model=“3000”, @make=“Linksys”>=>1,
Note each entry is a different object. This is the normal and correct
behaviour. When you do:

puts frequency[Router.new(‘Linksys’,‘2000’)]

I assume you meant this and not Car.new it creates yet another object which
of course is not in the hash and so returns 0.

Maybe the example in the Hash docs could be useful to the OP:

http://ruby-doc.org/core-2.0/Hash.html
Quoting:
"
Hash Keys
Two objects refer to the same hash key when their hash value is
identical and the two objects are eql? to each other.
A user-defined class may be used as a hash key if the hash and eql?
methods are overridden to provide meaningful behavior. By default,
separate instances refer to separate hash keys.
A typical implementation of hash is based on the object’s data while
eql? is usually aliased to the overridden == method:
(…)
"

I hope this helps.

e.

Ruby M. wrote in post #1107907:

def ==(other)
return false unless other.is_a?(Router)
make == other.make && model == other.model

That should be eql?, and @make/@model:

def eql?(other)
return false unless other.is_a?(Router)
@make.eql?(other.make) && @model.eql?(other.model)
end

end

You also need to override the hash method, e.g.:

def hash()
@make.hash ^ @model.hash
end

end

frequency = Hash.new(0)
models = %w(2000 3000 2000 3200)
models.each{|m| frequency[Router.new(‘Linksys’,m)] += 1}
puts frequency[Car.new(‘Linksys’,‘2000’)]

As noted, should be Router:

puts frequency[Router.new(‘Linksys’,‘2000’)]

All,

Thanks a lot !

Damm I forgot the simple concept of contract between eql and hashcode :smiley:

Again thanks !!

Per-erik Martin wrote in post #1107918:

Ruby M. wrote in post #1107907:

def ==(other)
return false unless other.is_a?(Router)
make == other.make && model == other.model

That should be eql?, and @make/@model:

def eql?(other)
return false unless other.is_a?(Router)
@make.eql?(other.make) && @model.eql?(other.model)
end

end

You also need to override the hash method, e.g.:

def hash()
@make.hash ^ @model.hash
end

end

frequency = Hash.new(0)
models = %w(2000 3000 2000 3200)
models.each{|m| frequency[Router.new(‘Linksys’,m)] += 1}
puts frequency[Car.new(‘Linksys’,‘2000’)]

As noted, should be Router:

puts frequency[Router.new(‘Linksys’,‘2000’)]

On Mon, May 6, 2013 at 7:22 PM, Ruby M. [email protected] wrote:

Damm I forgot the simple concept of contract between eql and hashcode :smiley:

I blogged about this a long time ago - in case you need a page for your
bookmarks :slight_smile:
http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html

Cheers

robert

On Mon, May 6, 2013 at 4:14 PM, Robert K.
[email protected]d wrote:

I blogged about this a long time ago - in case you need a page for your
bookmarks :slight_smile:
http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html

REALLY great blog post! Information like this is rather invaluable.

Robert K. wrote in post #1108013:

On Mon, May 6, 2013 at 7:22 PM, Ruby M. [email protected] wrote:

Damm I forgot the simple concept of contract between eql and hashcode :smiley:

I blogged about this a long time ago - in case you need a page for your
bookmarks :slight_smile:
http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html

Excellent this one is.

On 07/05/2013 07:14, Robert K. wrote:

your bookmarks :slight_smile:
http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html

Thanks for that Robert. BTW s/robuts/robust/.

Graham