Message Boards Message Boards

0
|
7663 Views
|
8 Replies
|
0 Total Likes
View groups...
Share
Share this post:

[?] Break outer Do loop by an incident in inner Do loop?

Posted 5 years ago

Hi Friends,

I have a code line having two "Do" loops, one within other. In certain situation arising within inner loop, I want the inner as well as outer "Do" loops to break simultaneously. How to achieve it ? The Break[] function I tried only breaks the inner loop, not the outer one. Here is a simplified example.

R[0] = 0;
dsc = {-6, -5, -4, -3, -2, -1, 0, 1, 2};
X = Reap[X = 1; 
   Do[Do[If[dsc[[k]] < 0, R[m] = R[m - 1] + 1; Sow[R[m]]; Sow[{m, k}];
       X = 1 + k; If[R[m] != R[m - 1], Break[]], Sow[{m, k}]; 
      Break[]], {k, X, 10}], {m, 1, 8}]][[2]]

The o/p of this code is

{{1,{1,1},2,{2,2},3,{3,3},4,{4,4},5,{5,5},6,{6,6},{7,7},{8,7}}}

Here, basically the inner Do loop breaks as soon as the dsc hits a non-negative number and there is no further advancement of R[m] after the m and k hit the values {6, 6} during two Do loops. What I want to achieve is the breaking of m loop as well once dsc[[k]] hits a positive number. So basically I want to see the o/p

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

Will appreciate any suggestion on it.

Thanks

POSTED BY: S G
8 Replies

To be clear, The "done" is arbitrary -- you can return whatever you want or Null.

I still do not understand the exact computation but here is a close example. For example, you can determine in advance the sublist of the k loop

dscShort = 
 dsc[[1 ;; (Position[dsc, _?NonNegative, 1, 1][[1, 1]] - 1)]]

I constructed a shortened version of dsc. Now you can map a function over that to do your second "loop"

MapIndexed[(rr[#2[[1]]] = rr[#2[[1]] - 1] + 1) &, dscShort]

I used MapIndexed because you want to use the "m" in your definition of R (I use lowercase -- it is always better so you do not step on Mathematica Symbols). Note that I did not use the value of dsc in the definition because you only used "m" in your example but #1 would refer to the dsc value in a more complex function.

I do not understand how you intend to use a 2 dimensional dsc but you can easily map the shortening function over a 2-d list for example:

multiShort[x_] := 
 Map[#[[1 ;; (Position[#, _?NonNegative, 1, 1][[1, 1]] - 1)]] &, x]

multiShort[dsc2D]

would give you a list of shortened dsc lists that you can now map over. I hope this helps.

Regards,

Neil

POSTED BY: Neil Singer

By the way, what alternative would you suggest instead of "Do", if it does not disturb my rest of the code, may try !! Thanks once again !

Take a look at this post from StackExchange for some alternatives to loops. Actually, Do can be a reasonably good option in some cases. It's usually For that you want to avoid.

POSTED BY: John Shonder
Posted 5 years ago

Thanks a lot Neil, appreciate your help. I was trying to "Throw" Break[] from k loop to m loop instead of "done", perhaps the reason why it was not working.

The only reason for insisting on "Do" is that I have already invested few months to write this code and would like stick to it. I started with "For", and then had to switch to "Do" after several issues.

By the way, what alternative would you suggest instead of "Do", if it does not disturb my rest of the code, may try !! Thanks once again !

POSTED BY: S G

Ok, (but I still think there are better ways)

You can use Throw as (John suggested above). Just change your second Break[] to a Throw[]. I also changed the order of the Throw[] and the following Sow so you only get output when the test is successful.

R[0] = 0;
dsc = {-6, -5, -4, -3, -2, -1, 0, 1, 2};
X = Reap[X = 1;
  Catch[Do[
    Do[
     If[dsc[[k]] < 0, R[m] = R[m - 1] + 1; Sow[R[m]]; Sow[{m, k}];
      X = 1 + k; If[R[m] != R[m - 1], Break[]],
      Throw["done"]; Sow[{m, k}]], {k, X, 10}], {m, 1, 8}]]]

I hope this helps.

Regards,

Neil

POSTED BY: Neil Singer
Posted 5 years ago

Thanks for the suggestions. It is just a simplified version of my problem where I am looking to break the inner and outer loops with the appearance of a non-negative number in a series. My original problem is much more complicated and it modifies the function R[m] (which is a 12 X 1 matrix) with each progressing value of integer m depending upon the each row of dsc, which is originally a 3 X 144 matrix (not 9 X 1 like in this simplified version).

The good thing is that this example is a correct representation of my problem and anything which may help in breaking the m cycle here, will work for original problem as well.

You might be correct with your evaluation of "Do" loops and I will keep it in mind for the next assignment, but here, if possible, I would prefer to continue with it.

Once again thanks for your interest in my problem and anticipating a valuable suggestion to solve it.

POSTED BY: S G

Using a "Do" in a list-based language like Mathematica is almost never the correct way to code something. Your looping construct in which the outer loop controls and alters the specification of the inner iterator is even more unusual. Please describe what you want the loop to do so we can propose a cleaner way to achieve that in MMA. For example:

  1. is the Reap and Sow used for your required output or is that just debugging your loops?
  2. Are you just counting the number of sequential negative elements in the beginning of your dsc list or is there something more going on that you need to achieve?

Regards,

Neil

POSTED BY: Neil Singer
Posted 5 years ago

Appreciate your suggestion. I looked into Throw/Catch, but the problem is that the condition to terminate m loop is dependent on k, that is dsc[[k]] >= 0. In this case if I put Throw[] under If[] condition in m loop only (outside k loop), it does not work.

Please suggest me if I am not conceiving it properly.

Thanks

POSTED BY: S G

Look up Throw and Catch.

POSTED BY: John Shonder
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract