繁体   English   中英

在Ruby早期逃避.each {}迭代

[英]escaping the .each { } iteration early in Ruby

码:

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

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

我该如何用?替换注释行? 有更好的方法吗? 更多Ruby惯用的东西?

虽然break解决方案有效,但我认为更实用的方法确实适合这个问题。 你想take前10个元素并打印它们,所以尝试

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

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

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使用take 的答案更好。

break适用于从循环中提前逃避,但它只是做items[0..9].each {|i| puts i} items[0..9].each {|i| puts i} (如果您所做的只是字面上打印完全没有任何更改的项目,您可以puts items[0..9] 。)

另一个变种:

puts items.first(10)

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

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

(另一个注意,很多人都提供某种形式的puts i.to_s ,但在这种情况下,不是.to_s冗余? puts会自动调用非字符串上的.to_s来打印出来,我想如果你想说puts 'A' + i.to_s等,你只需要.to_s 。)

另一种选择是

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

而且要把这个“红宝石”加了一下:

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! 无论如何,如果少于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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM