尽早在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中没有++
运算符。 使用do
和end
多行块也是惯例。 修改您的解决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个项目,然后离开“每个”循环。
使用throw
和catch
来完成这个,对这个例子做了一些改动:
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