2
$\begingroup$

I am interested in generating a 1D list of the upper-triangle elements of a matrix.

I can grab the indices of these elements by doing:

upperTrianglularIndices[dim_] := Subsets[Table[i, {i, val /. val -> dim}], {2}];

But I'm struggling to actually select the matrix elements using these indices.

If I have a function, then I know I can map-thread it using this code:

f @@ # & /@ upperTrianglularIndices[3]

which will return:

{f[1, 2], f[1, 3], f[2, 3]}

so my idea is to express my matrix as a function, function[matrix[[x]],x], and then use the above code to apply it to each index. I see that this works correctly like this:

(x \[Function] f[[x]]) @@ # & /@ upperTrianglularIndices[3]

But doesn't work when I specify that I want the function to be the selection of the matrix element:

(x \[Function] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}[[x]]) @@ # & /@ 
 upperTrianglularIndices[3]

This returns (with some errors):

{f[[1]], f[[1]], f[[2]]}

What is the problem here?

$\endgroup$
9
  • $\begingroup$ You could try using an undocumented internal function: Statistics`Library`UpperTriangularMatrixToVector[f] $\endgroup$
    – Carl Woll
    Commented Aug 26, 2020 at 17:43
  • $\begingroup$ What is the desired output? $\endgroup$
    – yarchik
    Commented Aug 26, 2020 at 18:07
  • $\begingroup$ @yarchik, the upper triangle (with or without diagonals) made to be a vector. So in this case, {2, 3, 6} or {1, 2, 3, 5, 6, 9} $\endgroup$ Commented Aug 26, 2020 at 18:11
  • $\begingroup$ @CarlWoll, I'm primarily interested in improving so my preference would be to learn how to do this using the basic syntax - but in the future, (when I'm confident but lazy) I would be interested in using that undocumented internal function. Do you happen to know if there's another command that grabs the diagonal elements too? $\endgroup$ Commented Aug 26, 2020 at 18:17
  • $\begingroup$ Diagonal returns the diagonal elements. $\endgroup$
    – Carl Woll
    Commented Aug 26, 2020 at 18:18

1 Answer 1

3
$\begingroup$
Clear["Global`*"]

Format[f[m_, n_]] := Subscript[f, m, n]

n = 3;

(mat = Array[f, {n, n}]) // MatrixForm

enter image description here

The indices are

upperTrianglularIndices[n_] :=
 Table[{i, j}, {i, n}, {j, i, n}] // Flatten[#, 1] &

upperTrianglularIndices[n]

(* {{1, 1}, {1, 2}, {1, 3}, {2, 2}, {2, 3}, {3, 3}} *)

The corresponding elements of the array are

mat[[##]] & @@@ upperTrianglularIndices[n]

enter image description here

$\endgroup$
2
  • $\begingroup$ Thank you. This is what I was looking for. One question: how do you think about when to use # or ##? $\endgroup$ Commented Aug 26, 2020 at 18:56
  • $\begingroup$ # takes the first argument, ## takes all arguments. $\endgroup$
    – Bob Hanlon
    Commented Aug 26, 2020 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.