# Get the number of specified elements from the SparseArray properties

In the sparse matrix, we have a list of properties: specified elements, dimension, default, and density. I am interested in getting this data without calculating them again. For an example, the following sparse matrix has four specified elements.

s = SparseArray[{{1, 1} -> 1, {2, 2} -> 2, {3, 3} -> 3, {1, 3} -> 4}]


I can calculate the number of specified elements of s by

Length@s["NonzeroValues"]


but I look for an option to get this information from s properties

• From the previous question, you know all the properties available. The length of "NonzeroValues" is not available, but you can calculate it, as you just did. Why is Length@s["NonzeroValues"] not an acceptable solution? I'm afraid it is not clear what fundamentally is the question you are asking. – rhermans Jul 29 '18 at 11:25
• I'm voting to close this question as off-topic because the OP already gave the optimal solution. – Henrik Schumacher Jul 29 '18 at 13:24
• At least if s well-formatted (e.g., if SparseArraySparseArraySortedQ[s] returns True), s["RowPointers"][[-1]] is a second possibility. But Length[s["NonzeroValues"]] is much safer. – Henrik Schumacher Jul 29 '18 at 13:28
• Also Length won't compute anything. s["NonzeroValues"] is a basic constitutent of a sparse array. Within the internal data type for sparse arrays (MSparseSparseArray), s["NonzeroValues"] is stored as a dense array (MTensor). The length (and dimensions) of a dense array are also stored in each MTensor object, so Length just reads off a value of a field of the MTensor. – Henrik Schumacher Jul 29 '18 at 13:39
• @HenrikSchumacher Shouldn't that be a clear sign that OP should self-answer and wait to see if a better answer comes along, rather than a close vote? – eyorble Jul 29 '18 at 21:05

You want a convenient accessor for the nonzero value count, which seems reasonable. You could define your own function, but you'd like to get it from properties instead.

I think this is a good use case for adding your own definition to a system function, which is allowed by the language. You just need to unprotect the symbol first,

Unprotect[SparseArray];
(s_SparseArray)["NonzeroValueCount"] := Length[s["NonzeroValues"]];
Protect[SparseArray];


It can be accessed like any other property now,

s["NonzeroValueCount"]
(* 4 *)


As an alternative to what you have already considered there is the property "Density":

slen = #["Density"] Times @@ Dimensions[#] &;

SparseArray[{{1, 1} -> 1, {2, 2} -> 2, {3, 3} -> 3, {1, 3} -> 4}] // slen

4.

• That seems a very convoluted way around Length@#["NonzeroValues"]&. – rhermans Jul 29 '18 at 13:53
• @rhermans Perhaps, but it is faster should that be important. I'll add an example. EDIT No, I'm wrong. I thought I'd looked at this before; it's not. Well there's egg on my face. :^) – Mr.Wizard Jul 29 '18 at 13:54
• SparseArraySparseArrayDimensions for speed then. – rhermans Jul 29 '18 at 13:55
• @rhermans I don't believe I've ever used that function before; let me try it. Thanks! – Mr.Wizard Jul 29 '18 at 13:56
• @Henrik I saw your comment after posting and it makes perfect sense now. I think what I was remembering that nonzero-Positions is a nontrival operation and would take measurable time, and confused that with values. I rarely if ever use "NonzeroValues" but "NonzeroPositions" was a very common tool for me in v7 before Pick` was optimized. – Mr.Wizard Jul 29 '18 at 14:10