Map vs. Table for index-specific operations on 2D arrays
Many index-specific operations can be implemented via MapIndexed
with a level specificaton. Your Power
example can be written as:
MapIndexed[#1^(#2[[1]]*#2[[2]]) &, test2D, {2}]
If you want better readability of indices you can define an auxiliary function:
myPower[x_, {n1_, n2_}] := x^(n1 n2);
MapIndexed[myPower, test2D, {2}]
Some index-specific operations can be implemented without indices at all. The last example in your question can be coded in a functional form as:
Map[Downsample[#, 2, 2] &, Map[Partition[#, 4] &, test2Dx], {2}]
This expression can be also rewritten in a more verbose way:
splitInBlocksOf4 = Partition[#, 4] &;
takeEvenElements = Downsample[#, 2, 2] &;
Map[takeEvenElements, Map[splitInBlocksOf4, test2Dx], {2}]
In many cases, the functional approach is shorter, faster and less error-prone than index-based solutions.
We don't need to avoid Table
in my view. In cases that Table
is more straightforward, just use Table
. If speed is concerned, Compile
it. Here is an example:
Can I generate a "piecewise" list from a list in a fast and elegant way?
Nevertheless, your 2 examples (especially 2nd one) don't belong to the cases that Table
is more straightforward, at least for someone familiar enough with list manipulation of Mathematica, I'm afraid. Do remember list manipulation is more than "Map
and its variants".
The following is my solution:
# /@ #@test2D &[#^Range@Length@# &]
Partition[#, 2] &@#[[2 ;; ;; 2]] & /@ test2Dx
BTW if test2D
is not ragged i.e. ArrayQ
returns True
for test2D
, I'll:
{dim1, dim2} = Range@Dimensions@test2D
((test2D^dim1)\[Transpose]^dim2)\[Transpose]
(* Alternatively: *)
test2D^Outer[Times, dim1, dim2]