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
开发者_如何学Python @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.
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?
You can also directly map the keys like this
hsh.values.map {|k| k[:x]}.reduce(:+) / hsh.size
精彩评论