How to Break Outer Cycle in Ruby

How to break outer cycle in Ruby?

What you want is non-local control-flow, which Ruby has several options for doing:

  • Continuations,
  • Exceptions, and
  • throw/catch

Continuations

Pros:

  • Continuations are the standard mechanism for non-local control-flow. In fact, you can build any non-local control-flow (subroutines, procedures, functions, methods, coroutines, state machines, generators, conditions, exceptions) on top of them: they are pretty much the nicer twin of GOTO.

Cons:

  • Continuations are not a mandatory part of the Ruby Language Specification, which means that some implementations (XRuby, JRuby, Ruby.NET, IronRuby) don't implement them. So, you can't rely on them.

Exceptions

Pros:

  • There is a paper that proves mathematically that Exceptions can be more powerful than Continuations. IOW: they can do everything that continuations can do, and more, so you can use them as a replacement for continuations.
  • Exceptions are universally available.

Cons:

  • They are called "exceptions" which makes people think that they are "only for exceptional circumstances". This means three things: somebody reading your code might not understand it, the implementation might not be optimized for it (and, yes, exceptions are godawful slow in almost any Ruby implementation) and worst of all, you will get sick of all those people constantly, mindlessly babbling "exceptions are only for exceptional circumstances", as soon as they glance at your code. (Of course, they won't even try to understand what you are doing.)

throw/catch

This is (roughly) what it would look like:

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

Pros:

  • The same as exceptions.
  • In Ruby 1.9, using exceptions for control-flow is actually part of the language specification! Loops, enumerators, iterators and such all use a StopIteration exception for termination.

Cons:

  • The Ruby community hates them even more than using exceptions for control-flow.

How to break inner loop and next for outer loop in ruby?

I got something in the similar matter:

count = 0 
10.times do |i|
(i..20).collect{ |ii| ii < rand(30) || break } || next
count += 1
end

So it is just boolean algebra. if condition is taken place, when all, i.e. result of collect method, isn't nil, so we need to next keyword worked, when result of collect is nil. Therefore we just set or operator between collect and next, in order to next is occuring when result of collect is nil.

How to break from a nested loop to a parent loop that is more than one level above which requires a value provided by the nested loop

You can use multiple break statements.

For example:

xxx.delete_if do |x|
result = yyy.each do |y|
result2 = zzz.each do |z|
if x + y == z
break true
end
end
break true if result2 == true
end
result == true
end

However I would definitely avoid this in your particular situation.

You shouldn't be assigning variables to the result of each. Use map, reduce, select, reject, any?, all?, etc. instead

It makes more sense to use any? to accomplish the same purpose:

xxx.delete_if do |x|
yyy.any? do |y|
zzz.any? do |z|
x + y == z
end
end
end

How to skip outer loop in ruby?

You can write:

array_1.each do |a1|
next if array_2.any? { |a2| a1.include?(a2) }
...
end

How to break out from a ruby block?

Use the keyword next. If you do not want to continue to the next item, use break.

When next is used within a block, it causes the block to exit immediately, returning control to the iterator method, which may then begin a new iteration by invoking the block again:

f.each do |line|              # Iterate over the lines in file f
next if line[0,1] == "#" # If this line is a comment, go to the next
puts eval(line)
end

When used in a block, break transfers control out of the block, out of the iterator that invoked the block, and to the first expression following the invocation of the iterator:

f.each do |line|             # Iterate over the lines in file f
break if line == "quit\n" # If this break statement is executed...
puts eval(line)
end
puts "Good bye" # ...then control is transferred here

And finally, the usage of return in a block:

return always causes the enclosing method to return, regardless of how deeply nested within blocks it is (except in the case of lambdas):

def find(array, target)
array.each_with_index do |element,index|
return index if (element == target) # return from find
end
nil # If we didn't find the element, return nil
end

Ruby/Rails break out of method inside loop

You have a couple of options for breaking out of a loop. Most simply, you can use break or return in your looping code.

In the context of your example above, it might be easier, if possible within the larger context of your application, to do the following:

def export_all
Category.find_each do |c|
begin
export_category(c)
rescue SpecificErrorIsBetterThanGenericExceptionIfPossible => e
break
end
end
end

def export_category(c)
sync_category(c)
end

It appears from your question that you want the loop in your export_all method to break when an exception is encountered. In such a case, I prefer my break/error handling code at that level.

Jump to next iteration of outer loop

This may be a bit redundant, but to better understand your question, I did:

quantity = 2
ids = ["a", "b"]

quantity.times do
puts "outer loop"
ids.each_with_index do |id, index|
puts "inner loop"
# a bunch of nested if/thens
if index == 0
puts "do something else"
puts "send termination email"
break
end
end
end

The output was:

outer loop
inner loop
do something else
send termination email
outer loop
inner loop
do something else
send termination email

if I take out the break, the output changes to:

outer loop
inner loop
do something else
send termination email
inner loop
outer loop
inner loop
do something else
send termination email
inner loop

This effectively saves a few inner loop iterations. Is this what your are looking for?



Related Topics



Leave a reply



Submit