我以前讨论过一种在Ruby中计算数组平均值的方法。但还有两个你可能会看到的平均数,不那么常用,但仍然有用。
计算一个中位数...
a = [1, 3, 2, 4, 6, 5, 7, 8]
sorted = a.sort # required
#=> [1, 2, 3, 4, 5, 6, 7, 8]
midpoint = a.length / 2 # integer division
#=> 4
if a.length.even?
# median is mean of two values around the midpoint
sorted[midpoint-1, 2].sum / 2.0
else
sorted[midpoint]
end
#=> 4.5
计算模式...
...使用Array#tally ,然后进行排序。
a = [1, 3, 3, 4, 6, 5, 7, 8]
tallied = a.tally
#=> {1=>1, 3=>2, 4=>1, 6=>1, 5=>1, 7=>1, 8=>1}
top_pair = tallied.sort_by { |_,v| v }.last(2)
#=> [[8, 1], [3, 2]]
if top_pair.size == 1
top_pair[0][0] # only one element, it is the mode
elsif top_pair[0][1] == top_pair[1][1]
nil # if count is same, no mode.
else
top_pair[1][0]
end
#=> 3
为什么?
#tally 方法在Ruby 2.7中被添加到Enumerable ,所以你可能会看到使用inject 的实现,这将表现得更糟。
我在写计算平均数的时候比较了使用Ruby本地方法和你自己的实现的性能。
还有什么问题吗?
毫无疑问,将这些计算进一步封装成方法是个好主意。
如果你正在做大量的这种计算,或者在性能很重要的情况下,你应该看一下 enumerable-statisticsgem。它有几个统计汇总方法的原生实现版本,混合在Array 和Enumerable 。
用C语言实现意味着这些方法要比用Ruby编程的任何版本的算法快得多。