性能:遍历除元素之外的数组

问题描述

| 我正在使用Ruby on Rails 3.0.7,我想遍历对象数组(类距离),但元素
id
等于
1
id
是指array [
1
]索引)。 我知道我可以对
each
语句使用
if
语句“内部”,并检查每个“当前” \“考虑”元素
if id == 1
。但是,由于数组中填充了大量数据,因此我想找到另一种方法,以便以更高性能的方式完成相同的事情(避免每次都运行
if
)。 我能怎么做?     

解决方法

        
a = [\'a\',\'b\',\'c\']
a.each_with_index.reject {|el,i| i == 1}.each do |el,i|
  # do whatever with the element
  puts el
end
IMHO是一种更好的选择方法,而不是使用您自己的显式
if
语句。但是,我相信它将产生与使用
if
相同的性能,甚至可能稍低一些。 如果像其他人建议的那样进行基准测试之后,您知道花费的时间肯定比您允许的时间慢,并且是导致缓慢的选择,那么可以很容易地通过多种方式修改此选择以删除选择:
a = [\'a\',\'c\']
n = 1
(a.first(n) + a.drop(n + 1)).each do |el|
  # do whatever with the element
  puts el
end
不幸的是,我相信这比运行简单的if还要慢。我认为可能具有提速潜力的一种是:
a = [\'a\',\'c\']
n = 1
((0...n).to_a+((n+1)...a.size).to_a).map{|i| a[i]}.each do |el|
  # do whatever with the element
  puts el
end
但这又很可能会变慢。 编辑 基准就是这个要点。这些结果实际上使我感到惊讶,拒绝是迄今为止最慢的选择,其次是范围。完全不删除元素之后的最高性能是使用
first
drop
选择周围的所有元素。 以未选择作为基准的百分比结果:
with if             146%
with first and drop 104%
without if          100%
显然,这在很大程度上取决于您对元素的处理方式,这是使用Ruby可以执行的最快操作进行的测试。操作越慢,这些差异就越小。一如既往:基准,基准,基准     ,         使程序生效 轮廓 优化 唐纳德·努斯说:   我们应该忘记小   效率,约占97%   时间:过早的优化是   万恶之源。 现在,您可以执行以下操作:
def f
  do_something
end

f 0
for i in 2..n
  f i
end
甚至:
def f
  yield 0
  for i in 2..@n
    yield i
  end
end

f do |i|
  do_something
end
但是您可能不想做任何事情,如果您做了,那只会在发现它很重要之后。 最后,假设这个丑陋的技巧实际上使您的服务器运行得更快。它值得吗?     ,        
if
语句是非常便宜的操作。您可以使用标准基准测试工具进行检查。
require \"benchmark\"

array = [1] * 100_000

Benchmark.bm do |bm|
  bm.report \"with if\" do
    array.each_with_index do |element,i|
      next if i == 1
      element - 1
    end
  end

  bm.report \"without if\" do
    array.each do |element|
      element - 1
    end
  end
end
结果:
                user     system      total        real
with if     0.020000   0.000000   0.020000 (  0.018115)
without if  0.010000   0.000000   0.010000 (  0.012248)
在100000个元素数组上,大约相差0.006秒。除非它成为瓶颈,否则您不应该关心它,我怀疑它会成为瓶颈。     ,        测试一个实际的for循环可能需要花费五分钟的时间。在Ruby圈子中可能对此并不满意,但这并不意味着它永远不值得使用。当您调用每个或地图或其他内容时,这些方法会以任何方式使用for循环。避免绝对。 这也取决于阵列可以得到多大,在大约n处,一个阵列可能变得比另一个阵列更快。在这种情况下,绝对不值得。 如果您不需要特定的元素,则可能不需要在数据库中存储该行数据。第1行与其余各行有什么区别,换句话说,为什么要跳过它? ID = 1的行中是否总是会有相同的数据?如果是这样,将其存储为常量可能会更好,并且会使您的问题无济于事。性能几乎总是会消耗更多的内存。 除非Rails 3所做的事情有所不同,并且您拉出数据并将id用作查找器键,否则id = 1将位于元素0中。 不幸的是,Knuth的报价被误解了很多,并习惯了糟糕的,低效的代码,如果程序员受过足够的教育,他们就不会编写这些代码,并思考了5秒钟。当然,花一个星期的时间尝试加速您不知道的代码是一个问题还是一个小问题,但这更多是Knuth所说的。性能是计算机科学中最容易被理解和滥用的概念之一。