Exiting .each early

I want to return part of a sorted array efficiently. The built in
iterators will search the entire array, but since I know it’s sorted, I
only need to collect the items up until they stop being in range.
However, its pretty wasteful to keep iterating after they start to fall
out of range…

How do I break a .each (or .collect, .reject, etc) early?

For example:

#########################################################
class Item
attr_reader :level

def initialize
@level = rand(100)
end
end

list = Array.new(10) {Item.new}

list.sort {|a, b| a.level <=> b.level}

under50 = list.find {|item| item.level < 50} # wasteful!
#########################################################

Is there a simple way to do this? A rather complex solution would be to
create a routine to find the index where the transition from valid to
invalid occurred, and slice the array to that index… but just being
able to iterate over half of the items (rather than all) would be
efficient enough for me at this point.

On 12.08.2008 18:51, Myrddin Emrys wrote:

I want to return part of a sorted array efficiently. The built in
iterators will search the entire array, but since I know it’s sorted, I
only need to collect the items up until they stop being in range.
However, its pretty wasteful to keep iterating after they start to fall
out of range…

How do I break a .each (or .collect, .reject, etc) early?

Exactly with break. :slight_smile:

irb(main):001:0> (1…10).each {|i| p i; break if i > 5}
1
2
3
4
5
6
=> nil

Is there a simple way to do this? A rather complex solution would be to
create a routine to find the index where the transition from valid to
invalid occurred, and slice the array to that index… but just being
able to iterate over half of the items (rather than all) would be
efficient enough for me at this point.

I rather suggest to use binary search. There is a library in RAA that
does it. Maybe there’s also a gem.

Kind regards

robert

Robert K. wrote:

On 12.08.2008 18:51, Myrddin Emrys wrote:
Exactly with break. :slight_smile:

For some reason I thought break wouldn’t work in this context… stupid
me. I should have checked.

I rather suggest to use binary search. There is a library in RAA that
does it. Maybe there’s also a gem.

I suspect so as well, but this particular application doesn’t need it.
Really, it doesn’t need to break early either (the arrays in question
are accessed frequently, but are under 100 items long), but for some
reason that inefficiency was really bothering me, regardless of its
actual impact. :slight_smile:

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs