如何从数组中求平均值?

如果我有一个数组:

[0,4,8,2,5,0,2,6]

平均得到3.375。


当前回答

这台电脑上没有ruby,但在这个程度上应该可以工作:

values = [0,4,8,2,5,0,2,6]
total = 0.0
values.each do |val|
 total += val
end

average = total/values.size

其他回答

我认为最简单的答案是

list.reduce(:+).to_f / list.size

您可以根据需要选择以下解决方案之一。

Bruteforce

[0,4,8,2,5,0,2,6].sum.to_f / [0,4,8,2,5,0,2,6].size.to_f

=> 3.375

方法

def avg(array)
  array.sum.to_f / array.size.to_f
end  

avg([0,4,8,2,5,0,2,6])
=> 3.375

猴子打补丁

class Array
  def avg
    sum.to_f / size.to_f
  end
end

[0,4,8,2,5,0,2,6].avg
=> 3.375

但我不建议对Array类进行猴子补丁,这种做法是危险的,可能会对您的系统造成不良影响。

为了我们的好处,ruby语言提供了一个很好的特性来克服这个问题,即Refinements,这是一种安全的方法来对ruby进行monkey补丁。

为了简化,使用细化,您可以猴子修补数组类,并且更改将只在使用细化的类范围内可用!:)

您可以在您正在处理的类中使用细化,并且您已经准备好了。

细化

module ArrayRefinements
  refine Array do
    def avg
      sum.to_f / size.to_f
    end
  end
end

class MyClass
  using ArrayRefinements

  def test(array)
    array.avg
  end
end

MyClass.new.test([0,4,8,2,5,0,2,6])
=> 3.375

无需重复数组(例如,非常适合一行程序):

[1, 2, 3, 4].then { |a| a.sum.to_f / a.size }
a = [0,4,8,2,5,0,2,6]
a.instance_eval { reduce(:+) / size.to_f } #=> 3.375

不使用instance_eval的版本如下:

a = [0,4,8,2,5,0,2,6]
a.reduce(:+) / a.size.to_f #=> 3.375
class Array
  def sum 
    inject( nil ) { |sum,x| sum ? sum+x : x }
  end

  def mean 
    sum.to_f / size.to_f
  end
end

[0,4,8,2,5,0,2,6].mean