# List consisting of positions of the matrix elements and the elements themselves

Given a 2D matrix I would like to make a list with elements consisting of positions of the matrix elements and the elements themselves. Let the matrix be

mat = {{a, b, c}, {s, v, t}, {k, l, m}};


then the aim is to obtain this:

(*   {{1, 1, a}, {1, 2, b}, {1, 3, c}, {2, 1, s}, {2, 2, v}, {2, 3, t}, {3,
1, k}, {3, 2, l}, {3, 3, m}} *)


The element a of the initial matrix has the list coordinates {1,1} and, therefore, is transformed into {1,1,a}, and so on. The solution is easy to obtain with the above matrix:

   Flatten[Map[{Position[mat, #], #} &,
mat, {2}] /. {{{a_, b_}}, c_} -> {a, b, c}, 1]

(*  {{1, 1, a}, {1, 2, b}, {1, 3, c}, {2, 1, s}, {2, 2, v}, {2, 3, t}, {3,
1, k}, {3, 2, l}, {3, 3, m}}  *)


The problem with this solution arises in the case, when not all elements in the initial matrix are different.

Any idea?

PS. One can do, of course, straightforwardly:

Flatten[Table[{i, j, mat[[i, j]]}, {i, 1, Dimensions[mat][[1]]}, {j,
1, Dimensions[mat][[1]]}], 1]


but I am looking for a faster approach.

• this is quite short and straightforward: MapIndexed[{Sequence @@ #2, #1} &, mat, {2}]. But what exactly would make you consider an approach "faster"? Dec 8, 2015 at 12:54
• Obfuscation frenzy: Flatten /@ List @@@ ArrayRules@(SparseArray@mat) // Most Dec 8, 2015 at 13:07
• Interesting that you mention that MapIndexed is faster. For me the table approach also seems to be slightly faster, at least if one keeps the Sequence for flattening the indices. For the Table approach I think you'd need Dimensions[mat][[2]] for the j loop counter for nonsquare matrices? Dec 8, 2015 at 13:28
• I added the performance-tuning tag, since you seemed to be asking for speed. Feel free to roll back, although I'm pretty sure some of our most expert Mathematica users monitor performance-tuning, so it's perhaps a good way to attract attention? :) Dec 8, 2015 at 16:50
• I would have done @Albert's snippet as MapIndexed[Append[#2, #1] &, mat, {2}]. Dec 9, 2015 at 8:07

Optimized Table wins, but in general setting Array is faster.

Array approach is inspired by the @LeonidShifrin vintage comment.

This version is fast and robust for 2D. For more dimentions needs tuning.

Array[{#1, #2, mat[[#1, #2]]} &, Dimensions[mat]]


The following one looks shortest and universal but indeed slow (due to dual Sequence burden; note that use of only one ## in any position does not diminish the speed seriously).

Array[{##, mat[[##]]} &, Dimensions[mat]]


For the small 2D problem at hand it is fine though:

mat = {{a, b, c}, {s, v, t}, {k, l, m}};
Flatten[Array[{##, mat[[##]]} &, {3, 3}], 1]


{{1, 1, a}, {1, 2, b}, {1, 3, c}, {2, 1, s}, {2, 2, v}, {2, 3, t}, {3, 1, k}, {3, 2, l}, {3, 3, m}}}

MapIndexed approaches are also elegant but not that fast for long arrays and should as well be tuned a bit for multi-dimensional arrays.

Sample:

Clear[longMat];
longMat = RandomInteger[10, {1000, 1000}];


Optimized conditions (formula has exact size of matrix):

Table[{i, j, longMat[[i, j]]}, {i, 1000}, {j, 1000}]; // Timing
(* {0.078125, Null} *)

Array[{#1, #2, longMat[[#1, #2]]} &, {1000, 1000}]; // Timing
(* {0.09375, Null} *)

-----------------------------------

MapIndexed[Append[#2, #1] &, longMat, {2}]; // Timing
(* {1.0625, Null} *)

Array[{##, longMat[[##]]} &, {1000, 1000}]; // Timing
(* {1.625, Null} *)

MapIndexed[{Sequence @@ #2, #1} &, longMat, {2}]; // Timing
(* {1.96875, Null} *)


Unknown 2D Matrix:

Array[{#1, #2, longMat[[#1, #2]]} &, Dimensions[longMat]]; // Timing
(* {0.109375, Null} *)

Table[{i, j, longMat[[i, j]]}, {i, Dimensions[longMat][[1]]}, {j,
Dimensions[longMat][[2]]}]; // Timing
(* {0.96875, Null} *) ----> "much slower"

----------------------------------------

MapIndexed[Append[#2, #1] &, longMat, {Length[Dimensions[longMat]]}]; // Timing
(* {1.09375, Null} *)

Array[{##, longMat[[##]]} &, Dimensions[longMat]]; // Timing
(* {1.64063, Null} *)

MapIndexed[{Sequence @@ #2, #1} &, longMat, {Length[Dimensions[longMat]]}]; // Timing
(* {1.98438, Null} *)