views:

879

answers:

3

Is there an easy way to obtain the average of an attribute in a collection?

For instance, each user has a score.

Given a collection of user(s) (@users), how can you get the average score for the group?

Is there anything like @users.average(:score)? I think I came across something like this for database fields, but I need it to work for a collection...

+2  A: 

For your question, one could actually do:

@users.collect(&:score).sum.to_f/@users.length if @users.length > 0

Earlier I thought, @users.collect(&:score).average would have worked. For database fields, User.average(:score) will work. You can also add :conditions like other activerecord queries.

Ryan Oberoi
David
The ampersand operator is a substitute for: @users.collect{ |user| user.score}Read up more about it on the web:http://eli.thegreenplace.net/2006/04/18/understanding-ruby-blocks-procs-and-methods/
Ryan Oberoi
+1  A: 

I use to extend our friend Array with this method:

class Array 
  # Calculates average of anything that responds to :"+" and :to_f
  def avg 
    blank? and 0.0 or sum.to_f/size 
  end
end
Fer
+1  A: 

Here's a little snippet to not only get the average but also the standard deviation.

class User
  attr_accessor :score
  def initialize(score)
    @score = score
  end
end

@users=[User.new(10), User.new(20), User.new(30), User.new(40)]

[email protected](0){|acc, user| acc + user.score} / @users.length.to_f
stddev = Math.sqrt(@users.inject(0) { |sum, u| sum + (u.score - mean) ** 2 } / @users.length.to_f )
Jonas Elfström