Evaluate a selected number of cells in a matrix
Flatten @ MapIndexed[Drop, M]
{4, 1, 3, 0, 4, 0}
Here is one way:
Flatten @ ReplacePart[M, {n_, n_} -> Nothing]
Or, probably faster for bigger M
:
Flatten @ Pick[M, IdentityMatrix@Length@M, 0]
Here's an approach that uses ArrayRules
to associate each element with its indices, and then pick out the one you want using Cases
. I use a Unique
symbol as a default for ArrayRules
so you get an explicit rule for every element; otherwise Cases
won't grab all the elements you want:
Cases[ArrayRules[M, Unique[]],
HoldPattern[{i_, j_} -> a_] /; i != j :> a]
(* {4, 1, 3, 0, 4, 0} *)
Here's a fairly efficient way of doing it with procedural code, using Sow
/Reap
.
Reap[
With[{n = Length@M},
Do[If[i != j, Sow@M[[i, j]]], {i, 1, n}, {j, 1, n}]]] /.
{{Null, {result_}} :> result,
{Null, {}} :> {}}
Here's a compiled procedural version that should be fast that's almost like yours, but avoids AppendTo
, which is generally bad news (and I don't think will even compile).
compiled =
Compile[{{matrix, _Real, 2}},
Module[{
m, n,
result,
fill = 0,
},
{m, n} = Dimensions[matrix];
result = ConstantArray[0., m*n];
Do[If[i != j, result[[++fill]] = matrix[[i, j]]], {i, 1, m}, {j, 1, n}];
Take[result, fill]]];
compiled[M]
(* {4., 1., 3., 0., 4., 0.} *)
Because the function is compiled and I assumed the type of the matrix was real, everything got returned as a machine real.