I'm rewriting this question in code:
many = 1000 # An expensive method. # # It returns some data or nil if no result is available. expensive_method = lambda do rand(5) == 0 ? nil : "foo" end # Now, let's collect some data and stop collecting when no more data is # available. # This is concise but doesn't work. collection = many.times.map do expensive_method.call || break end puts collection.is_a? Array # false # This is less concise but works. collection = [] many.times do collection << (expensive_method.call || break) end puts collection.is_a? Array # true # My inner Rubyist ponders: Is it possible to accomplish this more concisely # using map?
Collection- A collection represents a group of objects, known as its elements. Map- A map cannot contain duplicate keys. Each key can map to at most one value.
#collect is actually an alias for #map . That means the two methods can be used interchangeably, and effect the same behavior.
In Ruby, we use a break statement to break the execution of the loop in the program. It is mostly used in while loop, where value is printed till the condition, is true, then break statement terminates the loop. In examples, break statement used with if statement. By using break statement the execution will be stopped.
Sure seems the only way to do this in Ruby is a filter type method then passing results to map. I'm not sure if this works in 1.8, but in 1.9 you could:
[0,1,2,1,0].take_while {|val| val < 2}.map(&:some_function)
Or in the times
example
3.times.take_while {|count| count <= 1 } #=> [0,1]
Instead of using map
directly, build up your own collection and then use the fact that break
returns a value to abort early:
result = [0, 1, 2, 1, 0].each_with_object([]) { |val, accumulator| if val < 2 accumulator << val else break accumulator end } result # => [0, 1]
If we did just break
(instead of break accumulator
) then nil
would be implicitly returned and result
would just be set to nil
.
This solution has the advantage of only allocating a single accumulator Array and only having to loop once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With