If I wanted to do something like this:
collection.each do |i|
return nil if i == 3
..many lines of code here..
end
How would I get that effect? I know I could just wrap everything inside the block in a big if statement, but I'd like to avoid the nesting if possibl开发者_开发技巧e.
Break would not work here, because I do not want to stop iteration of the remaining elements.
next
inside a block returns from the block. break
inside a block returns from the function that yielded to the block. For each
this means that break
exits the loop and next
jumps to the next iteration of the loop (thus the names). You can return values with next value
and break value
.
#!/usr/bin/ruby
collection = [1, 2, 3, 4, 5 ]
stopped_at = collection.each do |i|
break i if i == 3
puts "Processed #{i}"
end
puts "Stopped at and did not process #{stopped_at}"
In this instance, you can use break to terminate the loop early:
collection.each do |i|
break if i == 3
...many lines
end
...of course, this is assuming that you're not actually looking to return a value, just break out of the block.
Although this is ancient, this still confuses me sometimes. I needed this for a more complicated use case with [].select {|x| }
/[].reject {|x| }
.
Common Use case
[1,2,3,4,5].select{|x| x % 2 == 0 }
=> [2, 4]
But I needed to yield a specific value for each iteration and continue processing
With more complicated logic:
[1,2,3,4,5].select{|x| if x % 2 == 0; next true; end; false }
=> [2, 4]
# you can also use `next(true)` if it's less confusing
Also, since it's relevant to the thread, using break
here will emit the single value you pass in if the conditional hits:
[1,2,3,4,5].select{|x| if x % 2 == 0; break(true); end; false }
=> true
[1,2,3,4,5].select{|x| if x % 2 == 0; break(false); end; false }
=> false
[1,2,3,4,5].select{|x| if x % 2 == 0; break('foo'); end; false }
=> "foo"
精彩评论