Assuming the @houses array is set up as follows:
house1.price = 10
house2.price = 20
house3.price = 30
@houses << house1
@houses << house2
@houses << house3
This is the starting point of our calculation and we want to find the average price of a house:
total = 0
average = 0
for h in @houses
total += h.price
end
average = total/@houses.size
This seems like quite a lot of typing just to get an average.
Is there a better way?
Use the inject
method on an enumerable collection. Inject lets you pass in an initial value for an 'accumulator' (0 in this case), then apply some operation to each element in the list, and return a new value for the accumulator to be passed into the next iteration.
The final value of the accumulator is then returned from the inject
call.
So in this case, we just add up all the house prices into the accumulator, then finally divide by the total number.
You can get funkier and probably compress it down more with some Ruby skillz, but this is reasonably understandable, and only iterates through the list once to add up the values.
@houses.inject(0){|total, house| total + house.price} / @houses.size
Madlep's answer will work in any version of Ruby from the past several years. But if you're using Ruby 1.8.7 or later, you can express it a little bit more concisely as @houses.collect(&:price).inject(:+)/@houses.size
.
Incidentally, I had assumed this technique would be slower since it has to loop twice, but thanks to optimizations in Ruby itself, it's actually much faster up to a couple million items in my tests on Ruby 1.8.7, and faster (but not by as much) even past 10 million items in Ruby 1.9. Goes to show you the importance of profiling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With