views:

210

answers:

3
+1  Q: 

ruby loop refactor

Hi All,

I have a loop that looks like this

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

aside from changing the way do_something_with is called, how can i make this perform better?

thx,

-C

p.s.

Since it appears that this is an 'O(n)' operation, there is apparently no performance to be gained here, so the answer i chose is one that uses a ruby method that already encapsulates this operation. thanks for your help everybody

+2  A: 

The performance of do_something_with is the main factor. Anything else would be micro-optimisation.

This should be O(n), you could work out a way to avoid the final check, but that's not going to be that costly in the grand scheme of things.

Garry Shutler
if that's the case, I guess my only other question would be, is there a ruby method that already encapsulates this type of procedure?
Chris Drappier
+6  A: 

As others have mentioned you're not going to improve the performance much, but you could do this more cleanly like so:

array.each_cons(2) do |a, b|
  do_something_with(b) if a == b
end
tgamblin
should next_item be 'b' here?
Chris Drappier
Interesting - I hadn't seen each_cons before.
Sarah Mei
@Chris Drappier: yes thanks -- just noticed that
tgamblin
@Sara Mei: It's in enumerable... there is also each_slice, which is the non-sliding window version.
tgamblin
although it sucks my performance loss is not coming from the loop, this is a pretty nice way of doing this.. thx :)
Chris Drappier
Note that each_cons and each_slice are only in native Ruby as of 1.9, although they do exist in the Enumerable extensions implemented in Rails from (at least, possibly earlier) 2.1.2 onwards
Mike Woodhouse
A: 

I tend to agree with Garry on the optimization potential, but it can certainly be written more simply.

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