我正在寻找一种方法来查找数组中最大元素 first 出现的值和索引(在ruby中)。我没有找到一种方法来实现这一目标,只需少于2行代码,并且没有超出我想要的数量。
首先我尝试了:
example = [1, 100, 2, 100, 3]
value, index = example.each_with_index.max
但是这给了我最大元素的 last 出现的索引。
我目前的做法是:
example = [1, 100, 2, 100, 3]
value = example.max
index = example.find_index(value)
哪个有效,但是如果最大元素的第一个和最后一个出现是数组的最后两个元素,那么我当前的代码必须遍历整个数组两次。
我对性能比对代码大小更感兴趣,但是如果有一个非浪费的单行解决方案会很棒!
答案 0 :(得分:3)
这是一次性解决方案,但如果它比OP的两遍解决方案更快,我会感到惊讶,因为Array#max和Array#find_index都在C中实现并且针对数组(与Enumerable
对应数据相对)。
value, index = example.each_with_index.max_by { |n,i| [n,-i] }
#=> [100, 1]
当您尝试example.each_with_index.max
时,您首先计算了
enum = example.each_with_index
#=> #<Enumerator: [1, 100, 2, 100, 3]:each_with_index>
我们可以将此枚举器转换为数组,以查看它将生成哪些元素。
enum.to_a
#=> [[1, 0], [100, 1], [2, 2], [100, 3], [3, 4]]
当Array#max发送到enum
时,它将enum
生成的元素排序为最大到最小,如下所示。
[[100, 3], [100, 1], [3, 4], [2, 2], [1, 0]]
此排序的原因在Array#<=>的文档的第三段中进行了解释。
这就是你获得
的原因enum.max
#=> [100, 3]
相比之下,我Enumerable#max_by在
中搜索最大值a = [[1, 0], [100, -1], [2, -2], [100, -3], [3, -4]]
是
a.max
#=> [100, -1]
所以返回[100, 1]
。
答案 1 :(得分:1)
我对表现更感兴趣
你真的应该衡量一下。你自己的解决方案比Cary的解决方案<强>快75倍(谁也应该测量)。
user system total real
Yours 0.484000 0.000000 0.484000 ( 0.485868)
Cary's 36.094000 0.000000 36.094000 ( 36.412679)
是的,您的解决方案遍历数组两次。但这是两次快速遍历。 Cary只有一次遍历,但它是慢。他为每个元素做了更多的工作,一个枚举器参与其中,并且他在Ruby代码中部分地执行它。
我的基准代码:
require 'benchmark'
example = (1..10**8).to_a
Benchmark.bm(7) do |x|
x.report("Yours") {
value = example.max
index = example.index(value)
}
x.report("Cary's") {
value, index = example.each_with_index.max_by { |n,i| [n,-i] }
}
end
我已将您的example.find_index
更改为example.index
。一样。只是简短的名字。
最快的单程解决方案(如果你出于某种原因坚持一个),我想出的是:
value, index = example[0], 0
i = 0
example.each do |v|
if v > value
value = v
index = i
end
i += 1
end
大约需要4.8秒,所以比Cary快7.5倍,但仍然比你的慢10倍。
底线:使用您自己的解决方案。你甚至可以把它做成一个简短的单行(但我不会):
index = example.index(value = example.max)