【问题标题】:How to modify an iterator while iterating over an array如何在迭代数组时修改迭代器
【发布时间】:2016-03-26 11:12:45
【问题描述】:

我想根据运行时确定的条件跳过循环 x 次。我该怎么做?

for i in (0..5)
  if i==0
    3.times {next} # i=i+3 also doesnt work
  end
  puts i
end

期待输出

3
4
5

编辑: 澄清一下,问题是 condition(即 i==0)和跳过 x 次迭代都是在运行时动态确定的,更复杂的例子:

condition = Array.new(rand(1..100)).map{|el| rand(1..10000)} #edge cases will bug out
condition.uniq!

for i in (0..10000)
  if condition.include? i
    rand(1..10).times {next} # will not work
  end
  puts i
end

【问题讨论】:

  • 不确定函数的确切输入和输出是什么。在您的示例中,为什么不直接使用 (3..5).each {|i| puts i}
  • @LeiChen,这显然应该这样做,所以为什么不发布答案呢?也许def skip_first(range, nbr_to_skip)
  • 请看我更复杂的例子
  • 对于您的“复杂”示例,我希望提前计算一个数组keepers,因此您可以只写for i in keepers....。那可能写成condition = Array.new(rand(1..4)).flat_map do |el| first = rand(1..20); [*first..first+rand(0..4)]; end.uniq # => [7, 8, 9, 18, 6]; keepers = [*1..20]-condition #=> [1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20]。我知道在其他情况下您需要在块内使用next if ....

标签: ruby loops iterator


【解决方案1】:

通过定义的倍数跳过的简单方法。

array_list = (0..5).to_a
# Use a separate enum object to hold index position
enum = array_list.each 
multiple = 3

array_list.each do |value|
  if value.zero?     
    multiple.times { enum.next }
  end   
  begin puts enum.next rescue StopIteration end
end

【讨论】:

  • 你可以写得更简洁:multiple = 3; enum = (0..5).each; loop do; multiple.times { enum.next } if enum.next.zero?; puts 'hi'; end"hi" 被打印三次。这是因为Enumerator#next 在尝试超出枚举末尾时引发StopIteration 异常,而Kernel#loop 通过跳出循环来处理异常。您可以改为写enum = (0..5).to_enum,这可以说更具描述性。
猜你喜欢
  • 1970-01-01
  • 2010-12-18
  • 2020-05-29
  • 2011-03-02
  • 2017-03-04
  • 2017-09-25
  • 2013-01-15
  • 2013-05-13
  • 2014-09-17
相关资源
最近更新 更多