在Ruby中从数组中查找最高、最低、总和、平均值和中位数。

30

我正在用Ruby创建一个箱线图生成器,并且需要计算一些东西。

假设我有这个数组:

arr = [1, 5, 7, 2, 53, 65, 24]

如何从上述数组中找到最小值(1)、最大值(65)、总计(157)、平均值(22.43)和中位数(7)?

谢谢。


建议将代码行 total = arr.inject(:+) 更改为 total = arr.inject(0, :+),以避免出现 nil 值。 - user1283153
2个回答

66
lowest = arr.min
highest = arr.max
total = arr.inject(:+)
len = arr.length
average = total.to_f / len # to_f so we don't get an integer result
sorted = arr.sort
median = len % 2 == 1 ? sorted[len/2] : (sorted[len/2 - 1] + sorted[len/2]).to_f / 2

4
如果 arr.length 可以被 2 整除,你需要更加小心地处理中位数。一个始终有效的方法是 do sortedarr = arr.sort ; medpt1 = arr.length / 2 ; medpt2 = (arr.length+1)/2 ; (sortedarr[medpt1] + sortedarr[medpt2]).to_f / 2 ; end,但显然这个方法更为耗费资源,也没有你在答案中给出的那么简洁明了。 - Aidan Cully
1
一个小提示:arr.inject(:+) 只能在 Ruby 1.8.7 或更高版本中使用(或者如果另一个库已经实现了 Symbol#to_proc,例如 Rails 的 ActiveSupport)。否则,arr.inject {|sum, n| sum + n} 将会起作用。 - Greg Campbell
3
arr.inject(:+)并不会调用Symbol#to_proc,当给定一个符号时,inject会直接调用rb_funcall(这比传递一个块要快很多(或者更糟的是使用Symbol#to_proc))。但你是对的,这只在1.8.7+版本中有效。 - sepp2k
由于您正在对数组进行排序以查找中位数,因此是否通过sorted.first和sorted.last查找最小值和最大值会更有效率? - David Aldridge
@DavidAldridge 从绝对意义上讲是的,但是排序的时间复杂度是O(nlogn),对于大型数据集,它将消耗掉min和max操作的O(n)。 - Fryie

1

查找最小值、最大值、总和和平均值很简单,可以像sepp2k的答案中所示那样轻松地以线性时间完成。

但是查找中位数就不那么简单了。天真的实现方法(排序,然后取中间元素)需要O(nlogn)的时间。

然而,有一些算法可以在线性时间内找到中位数(如中值-5算法)。其他算法甚至适用于任何种类的顺序统计量(比如,你想要找到第五小的元素)。其中的问题是,你必须自己实现它们,我不知道Ruby是否有这样的实现。

O(nlogn)已经相当快了,因此如果你不打算处理海量数据集(如果你需要对数据进行排序),那么这种方法就足够了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接