我怎样才能从一个块返回早期的东西?

如果我想做这样的事:

collection.each do |i|
return nil if i == 3


..many lines of code here..
end

我怎么才能得到那种效果?我知道我可以用一个大的 if 语句包装块中的所有内容,但是如果可能的话,我想避免嵌套。

中断不会在这里工作,因为我做 没有想停止迭代剩余的元素。

37774 次浏览

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.

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}"

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"