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.
MapIndexed[{Sequence @@ #2, #1} &, mat, {2}]
. But what exactly would make you consider an approach "faster"? $\endgroup$Flatten /@ List @@@ ArrayRules@(SparseArray@mat) // Most
$\endgroup$MapIndexed
is faster. For me the table approach also seems to be slightly faster, at least if one keeps theSequence
for flattening the indices. For theTable
approach I think you'd needDimensions[mat][[2]]
for thej
loop counter for nonsquare matrices? $\endgroup$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 monitorperformance-tuning
, so it's perhaps a good way to attract attention? :) $\endgroup$MapIndexed[Append[#2, #1] &, mat, {2}]
. $\endgroup$