假设我有以下数组:
views = [
{ :user_id => 1, :viewed_at => '2012-06-29 17:03:28 -0400' },
{ :user_id => 1, :viewed_at => '2012-06-29 17:04:28 -0400' },
{ :user_id => 2, :viewed_at => '2012-06-29 17:05:28 -0400' },
{ :user_id => 3, :viewed_at => '2012-06-29 17:06:28 -0400' },
{ :user_id => 1, :viewed_at => '2012-06-29 17:07:28 -0400' },
{ :user_id => 1, :viewed_at => '2012-06-29 17:08:28 -0400' },
{ :user_id => 3, :viewed_at => '2012-06-29 17:09:28 -0400' },
{ :user_id => 3, :viewed_at => '2012-06-29 17:16:28 -0400' },
{ :user_id => 3, :viewed_at => '2012-06-29 17:26:28 -0400' },
{ :user_id => 3, :viewed_at => '2012-06-29 17:36:28 -0400' },
{ :user_id => 1, :viewed_at => '2012-06-29 17:47:28 -0400' },
{ :user_id => 2, :viewed_at => '2012-06-29 17:57:28 -0400' },
{ :user_id => 3, :viewed_at => '2012-06-29 17:67:28 -0400' },
{ :user_id => 1, :viewed_at => '2012-06-29 17:77:28 -0400' }
]
假设数组按 Viewed_at
排序如果我想检索特定 user_id 的视图数组中的最后一个视图哈希,我可以执行以下操作:
views.reverse.detect { |view| view[:user_id] == 1 }
其中 detect 将返回一个枚举中的第一项,其中块的计算结果为true。
我的问题是:我假设反向方法有O(n)
费用,那么如何在不反转数组的情况下反向检测?或反向方法不是O(n)
?
答案 0 :(得分:21)
方法Array#reverse
在时间和空间上是O(n)。由于您不需要整个反转数组,您可以使用Array#reverse_each,即空间中的O(1)。实际上,这只与真正的大阵列有关。
views.reverse_each.detect { |view| view[:user_id] == 1 }
#=> {:user_id=>1, :viewed_at=>"2012-06-29 17:77:28 -0400"}
答案 1 :(得分:1)
这将获取块为真的最后一个对象的索引(如果没有匹配,则为nil)。
views.rindex{|view| view[:user_id] == 1}
对@toklands reverse_each
进行基准测试后(对我来说很惊讶)更快:
require 'benchmark'
ar = Array.new(100){rand(100)}
target = rand(100)
Benchmark.bm(15) do |x|
x.report('reverse_each'){1000.times{ar.reverse_each.detect(target)}}
x.report('rindex'){1000.times{ar.rindex(target)}}
end
# user system total real
#reverse_each 0.000000 0.000000 0.000000 ( 0.002981)
#rindex 0.020000 0.000000 0.020000 ( 0.012078)