0
$\begingroup$

I want to make a double loop with Do. Let me first make a simple example. Consider the following simple double loop

Do[f[i,j]=i*j,{i,{1,2}},{j,{1,2}}]

does the job for $(i,j)=(1,1),(1,2),(2,1),(2,2)$ respectively. Now, suppose that I just want to do the same job but for $(i,j)=(1,1),(2,2)$. Clearly, one can use if statements inside Do but I don't like such a solution since as the range of $(i,j)$ becomes large the process becomes time consuming. Also, if there is not any pattern for the range of loop indices $(i,j)$ then making use of if statements becomes complicated.

Now, let us express the general problem. Suppose that we have a random list for index $i$ and another random list for index $j$. I want to do a sequence of operations for each $(i,j)$ inside a Do loop. What is the best way to do this?

$\endgroup$
  • $\begingroup$ If you just want to loop over one variable you would write Do[f[i,i]=i*i,{i,1,2}]. Personally I would just store the numbers in a list flist=Table[i*i,{i,1,2}]. $\endgroup$ – Erich Mueller Jun 5 '17 at 12:31
  • $\begingroup$ @ErichMueller: This is not my original problem. I may restate my question to make it more clear $\endgroup$ – H. R. Jun 5 '17 at 12:55
1
$\begingroup$

Bastian already showed MapThread but that function builds output (and uses memory) that I suspect you do not want. Here is another approach using a single separate index:

a = {1,2};
b = {1,2};

Do[f[i,i] = a[[i]]*b[[i]], {i, 2}]

Update: looking again I think I misunderstood and instead you would want something like:

Do[(f[##] = #*#2) &[a[[i]], b[[i]]], {i, 2}]

In either case the index approach should be applicable with adjustment.

Consider also using an Association as an alternative to DownValues function definitions.

fn = <| MapThread[{#, #2} -> #*#2 &, {a, b}] |>
<|{1, 1} -> 1, {2, 2} -> 4|>

You can then use fn like fn[{1, 1}] to get your value.

Also be aware of Scan, which could be applied in this manner:

Scan[Apply[(f[##] = #*#2) &], {a, b}\[Transpose]]
$\endgroup$
  • $\begingroup$ Thanks. I think such an option for Do seems necessary! In fact, I have lots of other works to do inside my original Do loop and I just posted a simple example here. I have a random list for index $i$ and a random list for index $j$ and I want to do a list of operations for each $(i,j)$. Do you know any other alternatives. :) $\endgroup$ – H. R. Jun 5 '17 at 12:54
  • $\begingroup$ Please take a look at the updated question. :) $\endgroup$ – H. R. Jun 5 '17 at 12:59
  • $\begingroup$ I don't understand your objection to the single index approach. It seems applicable to your updated answer. If one were to make a "nicer" syntax for it would that be a solution in your eyes? If you actually what the behavior of Do this is probably the best way. There are related but distinct methods such as Scan but it is hard to recommend one thing over another without a better sense of what you are trying to accomplish. (I added a quick example of Scan for reference, in case my intent was not clear.) $\endgroup$ – Mr.Wizard Jun 5 '17 at 13:04
  • $\begingroup$ Ah! Sorry. you are right. Single index approach does the job nicely. :) My brain was just locked on something else! :) $\endgroup$ – H. R. Jun 5 '17 at 13:10
3
$\begingroup$

If you always have (1,1), (2,2), (3,3) etc. just use f[i,i] = i*i.

In general: Note that in Mathematica it is nicer to use functional coding style instead of a procedural one. For your case it would be most easy to use

MapThread[f[#1,#2] = #1*#2 &, {{1,2},{1,2}}]]
$\endgroup$
  • $\begingroup$ Then MapThread would be the easiest way: MapThread[f[#1,#2] = #1*#2 &, {list1, list2}] $\endgroup$ – Bastian Seifert Jun 5 '17 at 12:31
  • $\begingroup$ (+1) I usually have random lists. :) Also, my main code consist of many other commands in the loop which depend on $(i,j)$. Your solution is nice for just evaluating a function at some points. :) $\endgroup$ – H. R. Jun 5 '17 at 12:34
  • $\begingroup$ Please take a look at the updated question. :) $\endgroup$ – H. R. Jun 5 '17 at 12:59
  • $\begingroup$ If you want to use MapThread this could be done by defining a dummy function: fun[i_, j_] := Module[{}, Sequence of Operations] $\endgroup$ – Bastian Seifert Jun 5 '17 at 13:10

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.