【问题标题】:ruby loop refactor红宝石循环重构
【发布时间】:2010-10-22 03:50:28
【问题描述】:

我有一个看起来像这样的循环

def slow_loop(array)
 array.each_with_index do |item, i|
   next_item = array[i+1]
   if next_item && item.attribute == next_item.attribute
     do_something_with(next_item)
   end
 end
end

除了改变 do_something_with 的调用方式,我怎样才能让它表现得更好?

谢谢,

-C

附言

由于这是一个'O(n)'操作,显然这里没有性能可取,所以我选择的答案是使用已经封装了该操作的ruby方法的答案。谢谢大家的帮助

【问题讨论】:

  • 也许您应该让我们知道您有多少元素以及您想出的任何类型的基准数据?这应该是一个 O(n) 操作。
  • 如果这听起来很愚蠢,请原谅我,但是,什么是 O(n) 操作?
  • 基本上,操作O的时间与元素个数n直接相关
  • 值得注意的是,仅仅因为它是一个 O(n) 算法并不意味着您不能从中获得更多性能。很多时候,最好的算法是 O(n),但你仍然可以用病态的 O(n) 算法打自己的脚。例如,在存储行优先时迭代矩阵列优先。在您的情况下,这是一个非常简单的算法,并且没有太大的改进空间。但请记住,即使您应该首先检查算法的复杂性,但获得最佳性能通常与较大的常数因素有关。

标签: ruby arrays refactoring


【解决方案1】:

正如其他人所提到的,您不会大幅提高性能,但您可以像这样更干净地做到这一点:

array.each_cons(2) do |a, b|
  do_something_with(b) if a == b
end

【讨论】:

  • 这里的 next_item 应该是 'b' 吗?
  • 有趣 - 我以前没见过 each_cons。
  • @Sara Mei:在enumerable中……还有each_slice,就是非滑窗版本。
  • 虽然我的性能损失不是来自循环,但这是一个非常好的方法......谢谢 :)
  • 请注意,each_cons 和 each_slice 仅在 1.9 版本的原生 Ruby 中存在,尽管它们确实存在于 Rails 从 2.1.2 开始(至少,可能更早)实现的 Enumerable 扩展中
【解决方案2】:

do_something_with 的性能是主要因素。其他任何东西都是微优化。

这应该是 O(n),你可以想办法避免最终检查,但从总体上看,这不会是那么昂贵。

【讨论】:

  • 如果是这样,我想我唯一的另一个问题是,是否有一个 ruby​​ 方法已经封装了这种类型的过程?
【解决方案3】:

我倾向于同意 Garry 关于优化潜力的观点,但它当然可以写得更简单。

prev_attr = nil
my_array.each |item|
  do_something_with(item) if prev_attr and prev_attr == item.attribute
  prev_attr = item.attribute
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 2012-06-04
    • 2019-08-09
    相关资源
    最近更新 更多