如何从数组中求平均值?
如果我有一个数组:
[0,4,8,2,5,0,2,6]
平均得到3.375。
如何从数组中求平均值?
如果我有一个数组:
[0,4,8,2,5,0,2,6]
平均得到3.375。
当前回答
比.inject更快的解决方案是:
sum(0.0)/arr.size
参见这篇文章参考:https://andycroll.com/ruby/calculate-a-mean-average-from-a-ruby-array/
其他回答
打印数组。求和/数组。计数是我做到的方式
[1,2].tap { |a| @asize = a.size }.inject(:+).to_f/@asize
简短,但使用实例变量
一些顶级解决方案的基准测试(按效率最高的顺序排列):
大阵:
array = (1..10_000_000).to_a
Benchmark.bm do |bm|
bm.report { array.instance_eval { reduce(:+) / size.to_f } }
bm.report { array.sum.fdiv(array.size) }
bm.report { array.sum / array.size.to_f }
bm.report { array.reduce(:+).to_f / array.size }
bm.report { array.reduce(:+).try(:to_f).try(:/, array.size) }
bm.report { array.inject(0.0) { |sum, el| sum + el }.to_f / array.size }
bm.report { array.reduce([ 0.0, 0 ]) { |(s, c), e| [ s + e, c + 1 ] }.reduce(:/) }
end
user system total real
0.480000 0.000000 0.480000 (0.473920)
0.500000 0.000000 0.500000 (0.502158)
0.500000 0.000000 0.500000 (0.508075)
0.510000 0.000000 0.510000 (0.512600)
0.520000 0.000000 0.520000 (0.516096)
0.760000 0.000000 0.760000 (0.767743)
1.530000 0.000000 1.530000 (1.534404)
小数组:
array = Array.new(10) { rand(0.5..2.0) }
Benchmark.bm do |bm|
bm.report { 1_000_000.times { array.reduce(:+).to_f / array.size } }
bm.report { 1_000_000.times { array.sum / array.size.to_f } }
bm.report { 1_000_000.times { array.sum.fdiv(array.size) } }
bm.report { 1_000_000.times { array.inject(0.0) { |sum, el| sum + el }.to_f / array.size } }
bm.report { 1_000_000.times { array.instance_eval { reduce(:+) / size.to_f } } }
bm.report { 1_000_000.times { array.reduce(:+).try(:to_f).try(:/, array.size) } }
bm.report { 1_000_000.times { array.reduce([ 0.0, 0 ]) { |(s, c), e| [ s + e, c + 1 ] }.reduce(:/) } }
end
user system total real
0.760000 0.000000 0.760000 (0.760353)
0.870000 0.000000 0.870000 (0.876087)
0.900000 0.000000 0.900000 (0.901102)
0.920000 0.000000 0.920000 (0.920888)
0.950000 0.000000 0.950000 (0.952842)
1.690000 0.000000 1.690000 (1.694117)
1.840000 0.010000 1.850000 (1.845623)
我希望Math.average(values),但没有这样的运气。
values = [0,4,8,2,5,0,2,6]
average = values.sum / values.size.to_f
让我在竞争中引入一些可以解决零除问题的东西
a = [1,2,3,4,5,6,7,8]
a.reduce(:+).try(:to_f).try(:/,a.size) #==> 4.5
a = []
a.reduce(:+).try(:to_f).try(:/,a.size) #==> nil
但是,我必须承认,“try”是一个Rails助手。但你可以很容易地解决这个问题:
class Object;def try(*options);self&&send(*options);end;end
class Array;def avg;reduce(:+).try(:to_f).try(:/,size);end;end
顺便说一句:我认为空列表的平均值为零是正确的。零的平均值是零,不是0。这就是预期行为。但是,如果您更改为:
class Array;def avg;reduce(0.0,:+).try(:/,size);end;end
空数组的结果不会像我预期的那样是一个异常,而是返回NaN…我在Ruby中从未见过这种情况。;-)似乎是Float类的特殊行为…
0.0/0 #==> NaN
0.1/0 #==> Infinity
0.0.class #==> Float