如何在Ruby中打破外部循环?

sqougxex  于 12个月前  发布在  Ruby
关注(0)|答案(8)|浏览(98)

在Perl中,有一种打破外部循环的能力,如下所示:

AAA: for my $stuff (@otherstuff) {
         for my $foo (@bar) {
             last AAA if (somethingbad());
         }
      }

(语法可能是错误的),它使用循环标签从内部循环中断开外部循环。Ruby中有类似的东西吗?

8iwquhpp

8iwquhpp1#

throw / catch为例。通常情况下,下面代码中的外部循环将运行五次,但通过throw,您可以将其更改为您喜欢的任何内容,并在过程中中断它。考虑一下这段完全有效的ruby代码:

catch (:done) do
  5.times { |i|
    5.times { |j|
      puts "#{i} #{j}"
      throw :done if i + j > 5
    }
  }
end
ogq8wdun

ogq8wdun2#

你想要的是非本地控制流,Ruby有几个选项可以做到这一点:

  • 续,
  • 异常和
  • throw / catch
    继续

优点:

  • 延续是非本地控制流的标准机制。事实上,你可以在它们之上构建 * 任何 * 非本地控制流(子例程、过程、函数、方法、协程、状态机、生成器、条件、异常):它们几乎是GOTO的更好的双胞胎。

缺点:

  • Continuation不是Ruby语言规范的强制部分,这意味着某些实现(XRuby,JRuby,Ruby.NET,IronRuby)没有实现它们。所以,你不能依赖他们。

我知道了
优点:

  • 有一篇论文从数学上证明了连续性可以比连续性更强大。IOW:它们可以做延续能做的一切,甚至更多,所以你可以用它们来代替延续。
  • 它们是普遍可用的。

缺点:

  • 他们被称为“例外”,这使人们认为他们“只适用于特殊情况”。这意味着三件事:阅读你代码的人可能不理解它,实现可能没有针对它进行优化(而且,是的,在几乎所有的Ruby实现中,异常都非常慢),最糟糕的是,你会厌倦所有那些人不断地,无意识地胡言乱语“异常只适用于特殊情况”,只要他们瞥一眼你的代码。(当然,他们甚至不会试图理解你在做什么。
    throw / catch

这是(大致)它看起来的样子:

catch :aaa do
  stuff.each do |otherstuff|
    foo.each do |bar|
      throw :aaa if somethingbad
    end
  end
end

优点:

  • 与例外情况相同。
  • 在Ruby 1.9中,为控制流使用异常实际上是语言规范的一部分!循环、枚举器、迭代器等都使用StopIteration异常来终止。

缺点:

  • Ruby社区甚至比在控制流中使用异常更讨厌它们。
uinbv5nw

uinbv5nw3#

不没有
您的选择是:

  • 把循环放在一个方法中,并使用return从外部循环中断开
  • 从内部循环中设置或返回一个标志,然后在外部循环中检查该标志,并在设置标志时中断该标志(这有点麻烦)
  • 使用throw/catch跳出循环
km0tfn4u

km0tfn4u4#

while c1
 while c2
    do_break=true
 end
 next if do_break
end

或者“break if do_break”,取决于你想要什么

rnmwe5a2

rnmwe5a25#

或许这就是你想要的?(未测试)

stuff.find do |otherstuff|
  foo.find do
    somethingbad() && AAA
  end
end

find方法会一直循环,直到块返回一个非空值或者到达列表的末尾。

eqfvzcg8

eqfvzcg86#

在循环周围 Package 一个内部方法可以做到这一点。

test = [1,2,3]
test.each do |num|
  def internalHelper
    for i in 0..3 
      for j in 0..3
        puts "this should happen only 3 times"
        if true
          return
        end
      end
    end
  end
internalHelper
end

在这里,你可以在任何for循环中进行检查,并在条件满足时从内部方法返回。

b0zn9rqh

b0zn9rqh7#

我知道我会在早上后悔,但简单地使用一个while循环可以做到这一点。

x=0
until x==10
  x+=1
  y=0
  until y==10
    y+=1
    if y==5 && x==3
      x,y=10,10
    end
  end
  break if x==10
  puts x
end

if y==5 && x==3只是表达式变为true的一个例子。

7uzetpgm

7uzetpgm8#

您可以考虑添加一个标志,该标志在内部循环中设置,用于控制外部循环。
'next'外部循环

for i in (1 .. 5)
  next_outer_loop = false
  for j in (1 .. 5)
    if j > i     
      next_outer_loop = true if j % 2 == 0
      break      
    end          
    puts "i: #{i}, j: #{j}"
  end            
  print "i: #{i} "                                                                                                                                                                             
  if next_outer_loop
    puts "with 'next'"
    next         
  end            
  puts "withOUT 'next'"
end

“打破”外部循环

for i in (1 .. 5)
  break_outer_loop = false
  for j in (1 .. 5)
    if j > i
      break_outer_loop = true if i > 3
      break
    end
    puts "i: #{i}, j: #{j}"
  end
  break if break_outer_loop
  puts "i: #{i}"
end

相关问题