在Ruby中,我需要一种中值计算方法,该方法也适用于嵌套数组,类似于“ uniq”和“ sort_by”:对于那些我可以通过块定义的方法,应该考虑哪些嵌套数组值
class Array
def median
. . .
end
end
puts [[1,3],[2,5],[3,-4]].median{|z,w| z}
=> [2,5]
puts [[1,3],[2,5],[3,-4]].median{|z,w| w}
=> [1,3]
我确定我应该以某种方式处理“收益”,但是我不知道该怎么做。
答案 0 :(得分:2)
由于中位数需要排序,因此您可以将其委托给sort_by
并处理其结果:
class Array
def median(&block)
block = :itself unless block_given?
sorted = sort_by(&block)
if length.odd?
sorted[sorted.length / 2]
else
sorted[sorted.length / 2 - 1, 2]
end
end
end
示例运行:
[13, 23, 11, 16, 15, 10, 26].median # => 15
# hyperbole showing the block is used on single elements
count = 0; [13, 23, 11, 16, 15, 10, 26].median { |a| count += 1 } # => 16
# even length data set
# usually you'd average these, but that becomes trickier with nested arrays
[14, 13, 23, 11, 16, 15, 10, 26].median # => [14, 15]
# your examples:
[[1,3], [2,5], [3,-4]].median { |z,_| z} # => [2, 5]
[[1,3], [2,5], [3,-4]].median { |_,w| w } # => [1, 3]
# added [6, -6] to your examples:
[[1,3], [2,5], [3,-4], [6, -6]].median { |z,_| z } # => [[2, 5], [3, -4]]
[[1,3], [2,5], [3,-4], [6, -6]].median { |_,w| w } # => [[3, -4], [1, 3]]
您没有指定偶数数组应该发生什么。对于数学中位数(如果我没记错我的数学知识),可以对两个最中心的元素取平均值,但是接下来要问的是2个不同数组的平均值是什么样的问题。这采用返回中心元素和调用者必须决定如何处理它们的简单(对我们而言)方法。 (例如,如果它不是嵌套的另一个数组,或者如果它是一个人的列表,并且您想要按姓氏表示的中位数,该怎么办?)
答案 1 :(得分:0)
我假设数组的中位数定义如下。对于包含奇数个元素的数组a
,中位数为[m]
,其中m
是a
的元素,其中e <=> m
的正值为负。 a.size/2
个其他元素e
和e <=> m
对于其余a.size/2
个其他元素e
是非负的。对于元素数为偶数的数组,中位数为[m, n]
,其中m
和n
是a
的元素,其中m <=> n
为非正数, e <=> m
对a.size/2-1
个其他元素e
非正,而e <=> n
对其余a.size/2-1
个其他元素e
非负。>
class Array
def median
min_by(1+self.size/2, &:itself).pop(self.size.odd? ? 1 : 2)
end
end
[2, 4, 5, 3, 1].median
#=> [3]
[2, 6, 4, 5, 3, 1].median
#=> [3, 4]
[3, 6, 4, 5, 3, 1].median
#=> [3, 4]
['hamster', 'dog', 'fish', 'cat'].median
#=> ["dog", "fish"]
[[1, 3], [2, 5], [3, -4]].median
#=> [[2, 5]]
[[2,6], [3,-4], [1,3], [2,5]].median
# => [[2, 5], [2, 6]]
arr = [[[3,1], 1], [[4], 2], [[2,1], 4, 1], [[3,1], 0], [[1,2,3], 5]]
arr.median
#=> [[[3, 1], 0]]
在最后一个示例中
arr.sort
#=> [[[1, 2, 3], 5], [[2, 1], 4, 1], [[3, 1], 0], [[3, 1], 1], [[4], 2]]
请参见Enumerable#min_by。可选参数是Ruby v2.1中引入的。
答案 2 :(得分:-1)
flatten()是您的朋友在这里。它将嵌套的数组(或任何可枚举的数组)折叠为单个数组。然后,计算中位数变得很简单:
class Array
def median
array = self.flatten.sort
if array.size % 2 == 1
array[array.size / 2]
else
mid = array.size / 2
(array[mid] + array[mid-1]) / 2.0
end
end
def mean
self.flatten.reduce(:+) / self.flatten.size.to_f
end
end
这可让您执行以下操作:
irb> a
=> [[1, 3], [2, 5], [3, -4]]
irb> a.median
=> 2.5
irb> c
=> [[1, 2, 3, 6], [4, 5, [100]]]
irb> c.median
=> 4
irb> c.mean
=> 17.285714285714285
为了提高性能,您可能需要计算一次self.flatten,然后在该数组之外执行两个算术运算。但是,除非您使用大量数据,否则可能无关紧要,希望Ruby会为您优化它。但老实说,我不会担心性能。
[编辑,在@kiddorails指出我混淆了中位数和均值之后!谢谢,Kiddo!]