0
$\begingroup$

Apologies if this is a trivial question. It comes from an overall problem I am having with Mathematica. Specifically, within a Do I generated the elements of a (vector) list but it doesn't remember these outside the Do.

The general problem is the Do performs a fairly lengthy sequence of calculations including a numerical integration that I need done for a list (in i) of different k values, and so I want to not just plot the results but save them indefinitely for future use and not having to recompute the integrals every time. So, I am trying to assign secondary lists s[[i]]= inside the Do which it prints out ok inside the Do, but doesn't remember them after outside.

Overall I am having trouble transitioning to Mathematica's one-liner format from writing a long sequenced Do loop in Fortran or Basic.

$\endgroup$
  • 1
    $\begingroup$ I guess we need to see some code before we can tell what's going wrong. A small toy example as demonstration of the problem would be best. In general, assignments within a Do loop should stick. $\endgroup$ – Sjoerd C. de Vries Mar 9 at 17:18
  • 1
    $\begingroup$ Typically in M, the equivalent of s = ConstantArray[0., {n}]; Do[(*calculate value*); s[[i]] = value, {i, n}]; s is s = Table[[(*calculate value*); value, {i, n}]. $\endgroup$ – Michael E2 Mar 9 at 17:26
  • 1
    $\begingroup$ s = Table[(m = i^2; p = i^3); {i, m, p}, {i, 4}] works from Michael E2.. Gave me a better way to do the whole thing. Much obliged. However now stuck on how to plot the saved integrals, ie all the other columns against the first column eg here 2nd& 3rd vs first NB my first is parameter k. $\endgroup$ – simon Mar 9 at 23:43
5
$\begingroup$

As I read your post, you are wanting to calculate a result for each value in an input list, plot the result, and have the results available for later use. Here are two methods in typical MMA usage:

(* create an input list *)
in = Range[1, 5]

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

(* the calculation *)
(* this could be later inline but this is more readable *)
calc[ini_] := NIntegrate[x, {x, 0, ini}]

(* one method *)

out = Table[{in[[i]], calc[in[[i]]]}, {i, Length[in]}]

(* {{1,0.5000000000000006`},{2,2.000000000000002`},{3,4.\
500000000000005`},{4,8.000000000000009`},{5,12.500000000000016`}} *)

ListPlot[out, AxesLabel -> {"ini", "calc[ini]"}]

enter image description here

(* another method *)
out = Map[{#, calc[#]} &, in]

(* {{1, 0.5}, {2, 2.}, {3, 4.5}, {4, 8.}, {5, 12.5}} *)

(* the calculated values in list *)
out[[All, 2]]

(* {0.5000000000000006`,2.000000000000002`,4.500000000000005`,8.\
000000000000009`,12.500000000000016`} *)

Edit: Here is an example of reformatting a table with rows {x,y1,y2, . . yn} to produce a list of lists that can be fed to ListPlot.

(* example with multiple columns *)
(* each row is {x, y1, y2, . . . , yn *)

(* create example data *)
exampleData = Table[
    {x, Sin[x], Cos[x], Log[x]},
    {x, Pi/4, 4 Pi, Pi/4}] // N;

(* reformat a table as a list of lists *)
(* each list now has rows of {x,yn} *)
reformat[table_] := Module[{xList, yLists},
  xList = Transpose[table][[1]];
  yLists = Rest@Transpose[table];
  Transpose@{xList, #} & /@ yLists]

out2 = reformat[exampleData];

ListLinePlot[out2]

enter image description here

$\endgroup$
  • $\begingroup$ But I will have multiple columns in my saved list and want to plot all of them against the first column which is my parameter k. Sorry now stuck on how to generalise your 2 column case. $\endgroup$ – simon Mar 9 at 22:11
  • 1
    $\begingroup$ @simon, I have edited my answer to provide an example of reformatting such a table into a list of lists which can be fed to ListPlot. $\endgroup$ – David Keith Mar 9 at 23:54
  • $\begingroup$ I have copied and pasted that and is working on v7.. Great the way you wrote it as an operator . I appreciate all your help. $\endgroup$ – simon Mar 10 at 0:15
4
$\begingroup$

It is possible to try to write FORTRAN in Mathematica if that is really what you want to do.

Perhaps this example will help.

s[1]=.;s[2]=.;(*get rid of any prior values, just in case*)
{s[1],s[2]}=Reap[Do[
  (*stuff*)
  Sow[i,s[1]];
  (*stuff*)
  Sow[i^2,s[2]];
  Sow[-i,s[1]],
{i,3}]][[2]]

and replace (*stuff*) with the rest of your code

Then

s[1]

will have the value

{1,-1,2,-2,3,-3}

and

s[2]

will have the value

{1,4,9}

Reading this CollectingExpressionsDuringEvaluation might help understand what this is doing.

$\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.