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$
8
  • 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
    Commented Jul 12, 2019 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
    Commented Jul 13, 2019 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
    Commented Jul 13, 2019 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
    Commented Jul 13, 2019 at 8:11
  • 1
    $\begingroup$ What does "o/p" mean? What does "break the loop" mean for you? $\endgroup$
    – Roman
    Commented Jul 13, 2019 at 8:19

1 Answer 1

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 and acknowledge you have read our privacy policy.

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