Naming Multiple Variables In A Loop - wolfram-mathematica

first time asking a question on here. I am trying to make multiple variables in Mathematica which all have the same name except for the number after it. For example, if the list I am using has 7 members, it will make the variables: member1, member2, member3, member4, and so on. If this is unclear I left an example below of how I wished it would work. Hopefully it is an easy solution!
list = {1,2,3,4,5}
For[i = 1, i < 6, i++,
member[i] = list[i]
]

Try this
list = {1, 2, 3, 4, 5};
For[i = 1, i < 6, i++,
ToExpression["member"<>ToString[i]<>"="<>ToString[list[[i]]]]]
followed by
?member3
which should show you that member3 has been assigned a value of 3
This is creating a string and then evaluating it as a line of code.

You can use Symbol with Evaluate.
list = {1, 2, 3, 4, 5};
For[i = 1, i < 6, i++,
Evaluate[Symbol["member" <> ToString[i]]] = list[[i]]
]
member3
3
Alternatively, using Array instead of For.
Array[(Evaluate[Symbol["member" <> ToString[#]]] = list[[#]]) &, Length[list]]
And a version that clears pre-existing values.
Array[(With[{x = "member" <> ToString[#]},
Clear[x];
Evaluate[Symbol[x]] = list[[#]]]) &, Length[list]]

Related

Create variable names in loop

My aim is to create a lot of functions f_i in a loop. These functions depend on parameters a[[i]], which can be taken from array A = {a1, a2, ...}. In order to eliminate the influence of the interator i, which leads to the situation when all functions are the same, I aspire to create variable names for each iteration.
The example: suppose I have got the array W = {1,2,3, ..., 100} and I should create variables w1 = 1, w2 = 2, ..., w100 = 100. I am trying to do this with the help of a for-loop:
loc[expr1_, expr2_] :=
ToExpression[StringJoin[ToString[expr1], ToString[expr2]]];
For[i = 1, i <= 100, i++,
{
loc[w, i] = W[[i]];
}]
When I need to see which value variable wk contains, then wk is not defined. But loc[w, k] = k is known.
How can I define variables wi? Or is there another way to create functions in a loop?
Thanks in advance
The way you are using {} leads me to believe that you have prior experience with other programming languages.
Mathematica is a very different language and some of what you know and expect will be wrong. Mathematica only uses {} to mean that is a list of elements. It is not used to group blocks of code. ; is more often used to group blocks of code.
Next, try
W={1,2,3};
For[i=i,i<=3,i++,
ToExpression["w"<>ToString[i]<>"="<>ToString[i]]
];
w2
and see that that returns
2
I understand that there is an intense desire in people who have been trained in other programming languages to use For to accomplish things. There are other ways o doing that for most purposes in Mathematica.
For one simple example
W={1,2,3};
Map[ToExpression["z"<>ToString[#]<>"="<>ToString[#]]&,W];
z2
returns
2
where I used z instead of w just to be certain that it wasn't showing me a prior cached value of w2
You can even do things like
W={1,2,3};
loc[n_,v_]:=ToExpression[ToString[n]<>ToString[v]<>"="<>ToString[v]];
Map[loc[a,#]&,W];
a3
which returns
3
Ordinarily, you will use indexed variables for this. E.g.,
ClearAll[x, xs]
n = 4
xs = Array[Indexed[x, #] &, 4]
Example use with random data:
RandomSeed[314]
mA = RandomInteger[{0, 99}, {n, n}]
vb = RandomInteger[{0, 99}, n]
Solve[mA.xs == vb, xs]
This is just for illustration; one would ordinarily use LinearSolve for the example problem. E.g., MapThread[Rule, {xs, LinearSolve[mA, vb]}].
It would be simpler to use a function variable, e.g. w[1], but here is a method to define w1 etc.
Note Clear can clear assignments using string versions of the symbols.
W = {1, 2, 7, 9};
Clear ## Map["w" <> ToString[#] &, W]
Map[(Evaluate[Symbol["w" <> ToString[#]]] = #) &, W];
w9
9
Symbol /# Map["w" <> ToString[#] &, W]
{1, 2, 7, 9}
Alternatively, with a function variable . . .
Map[(w[#] = #) &, W]
{1, 2, 7, 9}
w[9]
9
Also, using the OP's structure
Clear[loc]
Clear[w]
Clear ## Map["w" <> ToString[#] &, W]
W = {1, 2, 3, 4};
loc[expr1_, expr2_] := StringJoin[ToString[expr1], ToString[expr2]]
For[i = 1, i <= 4, i++, Evaluate[Symbol[loc[w, i]]] = W[[i]]]
Symbol /# Map["w" <> ToString[#] &, W]
{1, 2, 3, 4}
Note Evaluate[Symbol[loc[w, i]]] = W[[i]]] has the advantage that if the data at W[[i]] is a string it does not get transformed as it would by using ToExpression.

How to find duplicate element in array and return duplicate index

I need to find duplicate latitude in an array and nudge it a bit to avoid marker display problem.
I searched and find a way to do it in ruby:
1.find duplicate element in ruby
(I consider sort array element and check adjacent element)
2.use array.indexof() to get its index(may have 3 or more duplicate element)
This works sure but I feel its not the best way. Is there a way to find duplicate and index of duplicate in one go?
Thanks in advance
EDIT:
I've find a way,check duplicate and change on spot.
But the problem is this function change all duplicate value to another duplicated value.
I think its because the main array is not updated during check and change procedure, attached is my code,anyway to improve it?
#ln=0
for #ln in 0..#checkLocation.length-1 do
if (!(#checkLocation.index(#existlat)==nil) && (#existlat!=nil))
#checkLocation[#ln]=#checkLocation[#ln]+0.00001
end
#existlat=#checkLocation[#ln]
end
a = [:a, :b, :c, :b, :d, :a, :e]
a.each_index.group_by{|i| a[i]}.values.select{|a| a.length > 1}.flatten
# => [0, 5, 1, 3]
Finding dupes is not very difficult if performance is not a real issue for you.
The most natural way would be to compare each element with all the other elements:
for (int i = 0; i < arraySize-1; ++i) {
for (int j = i+1; j < arraySize; ++j) {
if(array[i] == array[j]) changeDupe(array[j]);
}
}
The code above will allow you to change all the dupes.
Example in execution, changin dupes to 0:
Input: {1, 2, 3, 2, 1, 4, 5, 6, 8, 2}
Output: {1, 2, 3, 0, 0, 4, 5, 6, 8, 0}
Another way to achieve this is to use a second array. If you are using integer values, you can make it like this:
int input[10] = {1, 2, 3, 2, 1, 4, 5, 6, 8, 2};
bool output[10] = {false, false, false, false, false, false, false, false, false, false};
for (int i = 0; i < arraySize; ++i) {
if (output[input[i]] == false) changeDupe(input[i]));
else output[input[i]] = true;
}
However, if one of your elements is bigger than the size of your array you will have a boundary problem. Suppose you have the value 100, then you would be trying to access the 100th element of the boolean array.
If you want to use the second algorithm but you are not working with an integer array, you could use a map to map each value on your array to an int, and then use the map value to set the booleans.
A pseudocode would look like this:
Map<yourData, int> map;
map<someValue, 1>;
map[someValue] = 1; //work based on this return value;
Yeeeet another way is to sort the array before iterating over it, and stop once you hit a different number. This would diminish the number of times you iterate over the array, but you would be adding the sorting algorithm complexity (probably O(n log(n))).
The code would look something like this:
int i = 0;
while (i < arraySize-1) {
if(array[i] == array[i+1])
array[i] = 0;
i++;
}
Input: {1, 1, 2, 3, 3, 4, 5, 6, 7, 8};
Output: {0, 1, 2, 0, 3, 4, 5, 6, 7, 8}
Complexity:
for the first algorithm, you would have N*(N-1) which I would say is O(n²).
for the second is O(n), but restrictions apply.
for the third, it would be the sort + O(n) for the loop.

Difference between Lists

You are given 2 lists, the first with a elements and the second with b elements, with a < b.
For each element e in list a, you want to take a element f in list b, and replace e with e-f. You cannot use a element twice unless it appears in list b twice.
The problem is to find the minimum value of the largest element of list a.
For example, say list a is [1, 2, 3, 4], and list b is [5, 6, 7, 8, 9, 10, 11, 12]. We would take the e's to be 5, 6, 7, 8, so that list a becomes [5-1, 6-2, 7-3, 8-4], with the largest element being 4. So 4 is the answer.
Another example: if list a is [1, 4, 7] and list b is [-1, 3, 4, 5, 6, 7, 8], we would take the e's to be -1, 4, 7, so that list a becomes [2, 0, 0], and the answer is 2. So 2 is the answer.
I know this is poorly worded, if I could do anything to better word it, please let me know. I tried first sorting list a and list b, then did not know what to do.
If you could help, please do.
Thanks!
calculate the values of the list:
(java)
List listA = ...;
List listb = ...;
for(int i = 0; i < listA.size(); i++){
listA.set(i, listA.get(i) - listb.get(i));
}
find the highest value in listA:
iHighestValue = listA.get(0); //setting it to 0 would not work with lists containing only negative integers
for(int j = 1; j < listA.size(); j++){
if(listA.get(j) > iHighestValue)
iHighestValue = listA.get(i);
}
[Edit]: sorry, it doesn't show as code (don't know why)

Reducing length of list with Total and a threshold parameter

I'm looking for a way to reduce the length of a huge list with the Total function and a threshold parameter. I would like to avoid the use of For and If (coming from old habits).
Example :
List that I want to "reduce" :{1,5,3,8,11,3,4} with a threshold of 5.
Output that I want : {6,11,11,7}
That means that I use the Total function on the first parts of the list and look if the result of this function is higher than my threshold. If so, I use the result of the Total function and go to the next part of the list.
Another example is {1,1,1,1,1} with a threshold of 5. Result should be {5}.
Thanks!
EDIT : it is working but it is pretty slow. Any ideas in order to be faster?
EDIT 2 : the loop stuff (quit simple and not smart)
For[i = 1, i < Length[mylist] + 1, i++,
sum = sum + mylist[[i]];
If[sum > Threshold ,
result = Append[result , sum]; sum = 0; ]; ];
EDIT 3 : I have now a new thing to do.
I have to work now with a 2D list like {{1,2}{4,9}{1,3}{0,5}{7,3}}
It is more or less the same idea but the 1st and 2nd part of the list have to be higher than the thresold stuff (both of them).
Example : If lst[[1]] and lst[[2]] > threshold do the summuation for each part of the 2D list. I tried to adapt the f2 function from Mr.Wizard for this case but I didn't succeed. If it is easier, I can provide 2 independant lists and work with this input f3[lst1_,lst2_,thres_]:=
Reap[Sow#Fold[If[Element of the lst1 > thr && Element of the lst2, Sow##; #2, # + #2] &, 0, lst1]][[2, 1]] for example.
EDIT 4 :
You are right, it is not really clear. But the use of the Min## > thr statement is working perfectly.
Old code (ugly and not smart at all):
sumP = 0;
resP = {};
sumU = 0;
resU = {};
For[i = 1, i < Length[list1 + 1, i++,
sumP = sumP + list1[[i]];
sumU = sumU + list2[[i]];
If[sumP > 5 && sumU > 5 ,
resP = Append[resP, sumP]; sumP = 0;
resU = Append[resU, sumU]; sumU = 0;
];
]
NEW fast by Mr.Wizard :
f6[lst_, thr_] :=
Reap[Sow#Fold[If[Min## > thr , Sow##1; #2, #1 + #2] &, 0, lst]][[2,
1]]
That ~40times faster. Thanks a lot.
Thread[{resP, resU}] == f6[Thread[{list1,list2}], 5] True
I recommend using Fold for this kind of operation, combined with either linked lists or Sow and Reap to accumulate results. Append is slow because lists in Mathematica are arrays and must be reallocated every time an element is appended.
Starting with:
lst = {2, 6, 4, 4, 1, 3, 1, 2, 4, 1, 2, 4, 0, 7, 4};
Here is the linked-list version:
Flatten # Fold[If[Last## > 5, {#, #2}, {First##, Last## + #2}] &, {{}, 0}, lst]
{8, 8, 7, 7, 11, 4}
This is what the output looks like before Flatten:
{{{{{{{}, 8}, 8}, 7}, 7}, 11}, 4}
Here is the method using Sow and Reap:
Reap[Sow # Fold[If[# > 5, Sow##; #2, # + #2] &, 0, lst]][[2, 1]]
{8, 8, 7, 7, 11, 4}
A similar method applied to other problems: (1) (2)
The Sow # on the outside of Fold effectively appends the last element of the sequence which would otherwise be dropped by the algorithm.
Here are the methods packaged as functions, along with george's for easy comparison:
f1[lst_, thr_] :=
Flatten # Fold[If[Last## > thr, {#, #2}, {First##, Last## + #2}] &, {{}, 0}, lst]
f2[lst_, thr_] :=
Reap[Sow#Fold[If[# > thr, Sow##; #2, # + #2] &, 0, lst]][[2, 1]]
george[t_, thresh_] := Module[{i = 0, s},
Reap[While[i < Length[t], s = 0;
While[++i <= Length[t] && (s += t[[i]]) < thresh]; Sow[s]]][[2, 1]]
]
Timings:
big = RandomInteger[9, 500000];
george[big, 5] // Timing // First
1.279
f1[big, 5] // Timing // First
f2[big, 5] // Timing // First
0.593
0.468
Here is the obvious approach which is oh 300x faster.. Pretty isn't always best.
t = Random[Integer, 10] & /# Range[2000];
threshold = 4;
Timing[
i = 0;
t0 = Reap[
While[i < Length[t], s = 0;
While[++i <= Length[t] && (s += t[[i]]) < threshold ];
Sow[s]]][[2, 1]]][[1]]
Total[t] == Total[t0]
Timing[ t1 =
t //. {a___, b_ /; b < threshold, c_, d___} -> {a, b + c, d} ][[1]]
t1 == t0
I interpret your requirement as:
if an element in the list is less than the threshold value, add it to the next element in the list;
repeat this process until the list no longer changes.
So, for the threshold 5 and the input list {1,5,3,8,11,3,4} you'ld get
{6,3,8,11,3,4}
{6,11,11,3,4}
{6,11,11,7}
EDIT
I've now tested this solution to your problem ...
Implement the operation by using a replacement rule:
myList = {1,5,3,8,11,3,4}
threshold = 5
mylist = mylist //. {a___, b_ /; b < threshold, c_, d___} :> {a, b+c, d}
Note the use of ReplaceRepeated (symbolification //.).

automatize a mathematic procedure: I need industrial amouts of results, and I get one

I've the following simple code in mathematica that is what I want to a single output. But I want to get hundreds or thousands of it. How can I do?
Clear["Global`*"]
k = 2; Put["phiout"]; Put["omegadiffout"];
Random[NormalDistribution[0, 0.1]];
For[i = 1, i < 31,
rnd[i] = Random[NormalDistribution[0, 0.1]]; i++]
Table[rnd[i], {i, 1, 30}]
For[i = 1, i < 30,
rnddf[i] = rnd[i + 1] - rnd[i]; i++
]
diffomega = Table [rnddf[i], {i, 1, 29}];
Table[
Table [rnddf[i], {i, 1, 29}], {j, 1, 100}];
PutAppend[Table[
diffomega, {j, 1, 100}] , "diffomega"]
eqs0 = Table [
k*phi[i + 1] + k*phi[i - 1] - 2*k*phi[i] - rnddf[i] == 0, {i, 1,
28}];
eqs1 = eqs0 /. {phi[0] -> phi[30], phi[31] -> phi[1]};
Sum[phi[i], {i, 1, 29}];
eqs2 = Append[eqs1, - phi[1] - phi[27] - 3 phi[29] == 0];
eqs3 = eqs2 /. {phi[30] -> -Sum[phi[i], {i, 1, 29}]};
vars = Table [phi[i], {i, 1, 29}];
eqs = NSolve[eqs3, vars];
PutAppend[diffomega, eqs , "phiout"]
This put on file "phiout" and "omegadiffout" only the last value. I need hundreds of them. For each random generations I need an output.
Thanks in advance
The first thing you need to do, #Paulo, is tidy up your Mathematica so that you, and we, can see the wood for the trees. For example, your 8th statement:
Table[
Table [rnddf[i], {i, 1, 29}], {j, 1, 100}];
makes a large table, but the table isn't assigned to a variable or used in any other way. There seem to be other statements whose results aren't used either.
Next you should abandon your For loops and use the Mathematica idioms -- they are clearer for we who use Mathematica regularly to understand, easier for you to write, and probably more efficient too. Your statements
For[i = 1, i < 31,
rnd[i] = Random[NormalDistribution[0, 0.1]]; i++]
Table[rnd[i], {i, 1, 30}]
For[i = 1, i < 30,
rnddf[i] = rnd[i + 1] - rnd[i]; i++
]
diffomega = Table [rnddf[i], {i, 1, 29}];
can, if I understand correctly, be replaced by:
diffomega = Differences[RandomReal[NormalDistribution[0,0.1],{30}]];
Always remember that if you are writing loops in Mathematica you are probably making a mistake. The next change you should make is to stop using Put and PutAppend until you can build, in memory, at least a small example of the entire output that you want to write. Then write that to a file in one go with Save or Export or one of the other high-level I/O functions.
When you have done that, edit your code and explain what you are trying to do and I, and other SOers, will try to help further. Unfortunately, right now, your code is so un-Mathematica-al that I'm having trouble figuring it out.

Resources