尽早在Ruby中避免.each {}迭代

码:

c = 0 items.each { |i| puts i.to_s # if c > 9 escape the each iteration early - and do not repeat c++ } 

我想抓住前10个项目,然后离开“每个”循环。

我用什么来replace注释行? 有更好的方法吗? 更多Ruby的惯用语?

虽然break解决scheme的工作,我认为更多的function方法真的适合这个问题。 你想take前10个元素,并打印它们试试

 items.take(10).each { |i| puts i.to_s } 

Ruby中没有++运算符。 使用doend多行块也是惯例。 修改您的解决scheme产生:

 c = 0 items.each do |i| puts i.to_s break if c > 9 c += 1 end 

还有:

 items.each_with_index do |i, c| puts i.to_s break if c > 9 end 

请参阅each_with_index以及编程Ruby Break,Redo和Next 。

更新: Chuck的范围答案更像Ruby, nimrodm的答案使用更好。

break早期从循环逃跑的作品,但更多的是惯用的只是做items[0..9].each {|i| puts i} items[0..9].each {|i| puts i} 。 (如果你所做的只是在没有任何改变的情况下打印项目,你可以puts items[0..9] 。)

另一个变体:

 puts items.first(10) 

请注意,这适用于数组less于10个项目:

 >> nums = (1..5).to_a => [1, 2, 3, 4, 5] >> puts nums.first(10) 1 2 3 4 5 

(还有一点需要注意的是,很多人都提供了某种forms的puts i.to_s ,但是在这种情况下,不是.to_s冗余? puts会自动调用.to_s在一个非string上打印出来,我想。如果你想要说puts 'A' + i.to_s或者类似的话,你只需要.to_s 。)

另一个select是

 items.first(10).each do |i| puts i.to_s end 

对于我来说,读取更容易,而不是打断一个迭代器,并且如果没有足够多的话,将只返回尽可能多的项目。

这看起来像你想要的?

 10.times { |i| puts items[i].to_s } 
 items.each_with_index { |i, c| puts i and break if c <= 9 } 

有人问:

我想抓住前10个项目,然后离开“每个”循环。

使用throwcatch来完成这个,对这个例子做了一些改动:

 catch(:done) do c = 0 collected = [] items.each do |item| collected << item throw(:done, collected) if c == 9 # started at 0 c += 1 end collected # if the list is less than 10 long, return what was collected end 

简单地throw标签:done collected和正在等待的catch :done将返回collected

这个“ruby”:

 catch(:done) do items.inject([]) do |collected, item| throw(:done, collected) if collected.size == 10 collected << item # collected gets returned here and populates the first argument of this block end end 

我不知道为什么有些人拒绝使用inject而使用reduce (相当于)清空inject([])的空数组正在注入item s! 无论如何,如果less于10个项目, inject将返回collected

大多数答案都试图回答问题的意图,而不是问题的内容,而items.take(10)在这种情况下确实是非常有意义的。 但我可以想象要抓住我的100美元预算内的第一个项目。 那么你可以简单地:

 catch(:done) do items.inject({items: [], budget: 100}) do |ledger, item| remainder = ledger[:budget] - item.price if remainder < 0 throw(:done, ledger) else ledger.tap do |this| this[:items] << item this[:budget] = remainder end # tap just returns what is being tapped into, in this case, ledger end end end