我怎样才能提前从区块中归还东西?

How can I return something early from a block?

提问人:ryeguy 提问时间:3/26/2010 最后编辑:Timur Shtatlandryeguy 更新时间:10/13/2022 访问量:42304

问:

如果我想做这样的事情:

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

   ..many lines of code here..
end

我将如何获得这种效果?我知道我可以用一个大的 if 语句将块内的所有内容包装起来,但如果可能的话,我想避免嵌套。

Break 在这里不起作用,因为我不想停止其余元素的迭代。

Ruby 循环返回 中断

评论


答:

5赞 Sniggerfardimungus 3/26/2010 #1

在这种情况下,您可以使用 break 提前终止循环:

collection.each do |i|
  break if i == 3
  ...many lines
end

...当然,这是假设你实际上并不打算返回一个值,只是跳出块。

评论

0赞 sepp2k 3/26/2010
这不仅会从块返回,还会从每个块返回。因此,循环将结束,而不是继续下一个值。不确定这是否是预期的。
4赞 Chuck 3/26/2010
您可以在 Ruby 中使用一个值 — 将导致返回 5。breakbreak 5each
1赞 ryeguy 3/26/2010
谢谢,但我不想停止迭代。
221赞 sepp2k 3/26/2010 #2

next在块内从块返回。 在块内部,从屈服于块的函数返回。因为这意味着退出循环并跳转到循环的下一次迭代(因此是名称)。您可以使用 和 返回值。breakeachbreaknextnext valuebreak value

评论

2赞 Francesco Belladonna 9/21/2013
break value对我不起作用,但工作得很好。多谢。next value
5赞 WattsInABox 12/20/2013
我不确定你对 next 和 break 的定义是否正确。至少,它们令人困惑。break 退出最里面的循环,Next 将你移动到下一个迭代。来源: tutorialspoint.com/ruby/ruby_loops.htm
5赞 sepp2k 12/20/2013
@WattsInABox,并且绝不是特定于循环结构的,因此您链接的文章非常具有误导性(因为它严重暗示了相反的内容)。我的描述在块内使用时绝对是正确的(请注意,在 Ruby 中很少(如果有的话)使用,因此 99% 的 和 的使用都在块内)。nextbreaknextbreakwhilefornextbreak
0赞 WattsInABox 12/21/2013
我想你的意思是非循环块。这就是令人困惑的地方。另外,我不同意你 99% 的断言,但这是一个不同的论点。
0赞 xander-miller 2/26/2017
我一直在 Array 类上寻找一个特定的方法,因为我习惯于拥有 .detect、.map、.reduce 等好东西。我知道当我找不到这样的东西时,我错过了一些明显的东西。谢谢。
14赞 JD. 3/26/2010 #3
#!/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}"
0赞 Michael 10/13/2022 #4

虽然这很古老,但有时这仍然让我感到困惑。我需要它来使用/进行更复杂的用例。[].select {|x| }[].reject {|x| }

常见用例

 [1,2,3,4,5].select{|x| x % 2 == 0 }
 => [2, 4] 

但是我需要为每次迭代生成一个特定的值并继续处理

使用更复杂的逻辑:

[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

此外,由于它与线程相关,因此如果条件命中,使用 here 将发出您传入的单个值:break

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