2
$\begingroup$

I have a code line having two Do loops, one within other. In certain situation arising within inner loop, I want the outer Do loop to break. How to achieve it ?

Here is a simplified example.

X = {{-10, 1, 1}, { 8, 2, 2},  {-7, 3, 1}, {2, 4, 2}};
XX = Reap[
   Do[Do[If[X[[k, 1]] < 0, R = m*X[[k, 2]]; Sow[R], R = m*X[[k, 3]]; 
      Sow[R]], {k, 1, 4}], {m, 1, 5}]][[2]]

The o/p of this code is

{{1, 2, 3, 2, 2, 4, 6, 4, 3, 6, 9, 6, 4, 8, 12, 8, 5, 10, 15, 10}}

Now for example, the element "9" appears in the o/p for the m = 3 cycle. I want to break the m loop for the next value of m as soon as "9" appears in the o/p. So in this case, the m cycle should stop at m = 3 instead of going up to 5. The o/p in that case should be

{{1, 2, 3, 2, 2, 4, 6, 4, 3, 6, 9, 6}}

I tried the beard combination of Break & Catch/Throw as shown below, but not able to make it work.

    X = {{-10, 1, 1}, { 8, 2, 2},  {-7, 3, 1}, {2, 4, 2}};
XX = Reap[
       Do[Catch[
         Do[If[X[[k, 1]] < 0, R = m*X[[k, 2]]; Sow[R]; 
           If[R == 9, Throw[Break[]]], R = m*X[[k, 3]];
           Sow[R]]; If[R == 9, Throw[Break[]]], {k, 1, 4}]], {m, 1, 
         5}]][[2]]

Will appreciate any help.

thanks

$\endgroup$
  • 3
    $\begingroup$ See Return. If that does not do what is required, post a minimal working example and explain what exactly you want. $\endgroup$ – Bob Hanlon Jul 12 at 13:57
  • $\begingroup$ In this case you can also use multiple iterators in Do since the number of inner loops doesn't depend on the outer loop. Then anything (Break[], Return[..., Do], Throw/Catch) will work. $\endgroup$ – b3m2a1 Jul 13 at 3:06
  • $\begingroup$ "Break" is not working for sure as it breaks the inner loop, not the outer. Catch/Throw looks promising, but perhaps I am not able to use it properly. I have added the code line in the original question, will appreciate any suggestion. $\endgroup$ – user49535 Jul 13 at 7:56
  • $\begingroup$ Throw[Break[]] is a strange construct. What should it achieve? Why don't you use Throw with a normal argument? $\endgroup$ – Roman Jul 13 at 8:11
  • 1
    $\begingroup$ What does "o/p" mean? What does "break the loop" mean for you? $\endgroup$ – Roman Jul 13 at 8:19
4
$\begingroup$

Throw/Catch would probably work:

Catch[
  Do[
    Do[Print[{i, j}];
       If[j == 7, Throw[7]],
    {j, 10}],
  {i, 10}]]

(*    {1,1}    *)
(*    {1,2}    *)
(*    {1,3}    *)
(*    {1,4}    *)
(*    {1,5}    *)
(*    {1,6}    *)
(*    {1,7}    *)

(*    7    *)

The advantage of Throw over Break is that the latter quits only the innermost loop, whereas for the former you can decide how many loops to quit by setting the Catch appropriately.

Update: you seem to want to break only the outer loop but let the inner one finish the current iteration. This could work:

X = {{-10, 1, 1}, {8, 2, 2}, {-7, 3, 1}, {2, 4, 2}};
stop = False;
XX = Reap[Do[Do[If[X[[k, 1]] < 0, R = m*X[[k, 2]]; Sow[R];
                If[R == 9, stop = True], R = m*X[[k, 3]];
                Sow[R]]; If[R == 9, stop = True], {k, 1, 4}];
             If[stop, Break[]], {m, 1, 5}]][[2, 1]]
(*    {1, 2, 3, 2, 2, 4, 6, 4, 3, 6, 9, 6}    *)

The trick here is to set a flag stop in the inner loop, and at the end of the inner loop check this flag and conditionally break the outer loop.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.