I have written a code to Dot a row (conjugate of that) of mm to the next one:
mm={{1,2,I},{I,I,3},{2,6,I},{1,6,4},{1,4,5}}
fIdD = ConstantArray[0, {Dimensions[mm][[1]] - 1, 2}];
Do[
fIdD[[j]][[1]] = j;
fIdD[[j]][[2]] = Dot[mm[[j]]\[Conjugate], mm[[j + 1]]]
, {j, 1, Dimensions[mm][[1]] - 1}];
Is there any possibility to use of mathematica syntax instead of this code for this aim(dot a conjugated row to the next one).
fIdD={{1, 0}, {2, -5 I}, {3, 38 - 4 I}, {4, 45}}
And if I am going to plot the {{1,Norm[0]},{2,Norm[-5I]},{3,Norm[38-4I]},{4,Norm[45]}}
with the ListPlot
. same as this: however it is wrong: ListPlot[{#1, Norm[ #2]}, & fIdD]
?!
Answer
I would simply do
Dot[Conjugate[#1], #2] & @@@ Partition[mm, 2, 1]
and do away with the sequential numbers, as those are easy enough to generate when needed any way (MapIndexed
?) ListPlot
does not need these indices.
But instead of jumping straight to the solution, let's take your code and improve it step by step.
Instead of
arr[[i]][[j]]
you can writearr[[i,j]]
. This is simpler and more readable.You are pre-initializing an array of known dimensions and then compute each element. This is never necessary in Mathematica. This is what
Table
is for.At this point we have
Table[
{j, Conjugate[mm[[j]]].mm[[j + 1]]},
{j, 1, Dimensions[mm][[1]] - 1}
]Much simper than the original code.
Additionally,
Dimensions[mm][[1]]
is simpler and clearer asLength[mm]
.When you use the iterator in
Table
to index an array, there are usually simpler ways. Instead ofTable[ f[ arr[[i]] ], {i, 1, Length[arr]}]
we can always writeTable[f[elem], {elem, arr}]
.But here you need to iterate through consecutive pairs of elements, not each element.
Partition
can make a list of pairs (or tuples) from a simple list.Partition[{a,b,c,d}, 2]
would give{{a,b}, {c,d}}
whilePartition[{a,b,c,d}, 2, 1]
will give{{a,b}, {b,c}, {c,d}
. This latter is what you need.This changes our code to
Table[
Conjugate[elem[[1]]].elem[[2]],
{elem, Partition[mm, 2, 1]}
]Instead of
elem[[1]]
people often writeFirst[elem]
, which might be more readable, depending on context. Since we have a list of pairs, in this particular caseelem[[2]]
would beLast[elem]
.You might rightly argue that this change is not really a simplification, and it also loses the integer index form the result. But it leads up to the next step.
When we have a list of the form
list = {{x1,y1}, {x2,y2}, ..., {xn,yn}}
, and we need to transform it to{f[x1,y1], f[x2,y2], ..., f[xn,yn]}
, one pattern I like to use isf @@@ list
This is short for
Apply[f, list, {1}]
, please look upApply
. If we already have a pre-defined functionf
, this makes for very simple and clear code. If we don't, we can constructf
on the fly as a pure function.This gives us the final version:
result = Dot[Conjugate[#1], #2] & @@@ Partition[mm, 2, 1]
One reason why I like this style is that I find
#1
much more readable thanelem[[1]]
. Too many brackets give me a headache :-)
To re-insert the integer indices, you can use
Transpose[{Range@Length[result], result}]
But in applications that need the index of each element, MapIndexed
can be useful too. MapIndexed[{First[#2], #1} &, result]
is another way to get the result, though I'd integrate MapIndexed
with the step that ultimately uses these indices.
ListPlot
does not need these indices, it automatically assumes x coordinates to be 1, 2, ... if they're not given. So plotting is as simple as
ListPlot[ Norm /@ result ]
f /@ list
is short for Map[f, list]
, please look up Map
.
As you can see, Mathematica has many ways to do the same thing, and it's up to you to choose one. I hope you found this little introduction educational.
Comments
Post a Comment