views:

82

answers:

1

In Ruby, I have a hash of objects. Each object has a type and a value. I am trying to design an efficient function that can get the average of the values of all of objects of a certain type within the hash.

Here is an example of how this is currently implemented:

#the hash is composed of a number of objects of class Robot (example name)
class Robot
  attr_accessor :type, :value

  def initialize(type, value)
    @type = type
    @value = value
  end

end


#this is the hash that inclues the Robot objects
hsh = { 56 => Robot.new(:x, 5), 21 => Robot.new(:x, 25), 45 => Robot.new(:x, 35), 31 => Robot.new(:y, 15), 0 => Robot.new(:y, 5) }


#this is the part where I find the average
total = 0
count = 0
hsh.each_value { |r|  
if r.type == :x        #is there a better way to get only objects of type :x ?
  total += r.value 
  count += 1
end
} 

average = total / count

So my question is:

is there a better way to do this that does not involve looping through the entire hash?

Note that I can't use the key values because there will be multiple objects with the same type in the same hash (and the key values are being used to signify something else already).

If there is an easy way to do this with arrays, that would also work (since I can convert the hash to an array easily).

Thanks!

EDIT: fixed error in my code.

+4  A: 
hsh.values.select {|v| v.type == :x}.map(&:value).reduce(:+) / hsh.size

I am trying to design an efficient function that can get the average of the values of all of objects of a certain type within the hash

Unless I misunderstood what you are trying to say, this is not what the code you posted does. The average value of the :x robots is 21 (there's 3 :x robots, with values 5, 25 and 35; 5 + 25 + 35 == 65 and 65 divided by 3 robots is 21), but your code (and mine, since I modeled mine after yours) prints 13.

is there a better way to get only objects of type :x ?

Yes. To select elements, use the select method.

is there a better way to do this that does not involve looping through the entire hash?

No. If you want to find all objects with a given property, you have to look at all objects to see whether or not they have that property.

Do you have actual hard statistical evidence that this method is causing your performance bottlenecks?

Jörg W Mittag
thanks, I fixed the error in my code. I don't have hard statistical evidence that this is what is causing the performance bottlenecks, but I am pretty sure it is, because this method is being called several hundreds of times each iteration of my program. Do you have any suggestions for tools or methods that can help me performance test my program?
Andrew