Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you concisely get the average house price from an array of houses?

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?

like image 553
M. Pelosi Avatar asked Nov 29 '22 05:11

M. Pelosi


2 Answers

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
like image 144
madlep Avatar answered Dec 10 '22 08:12

madlep


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.

like image 23
Chuck Avatar answered Dec 10 '22 08:12

Chuck