Find matrix size without using `size` in MATLAB

Suppose I want to find the size of a matrix, but I cannot use any functions like size , numel and length . Are there any neat ways to do this? I can come up with several versions using loops, like the ones below, but can this be done without loops?

 function sz = find_size(m) sz = [0, 0] for ii = m' %' or m(1,:) (probably faster) sz(1) = sz(1) + 1; end for ii = m %' or m(:,1)' sz(2) = sz(2) + 1; end end 

And for the record: This is not homework, it is out of curiosity. Although solutions to this issue will never be useful in this context, it is possible that they provide new knowledge in terms of using certain functions / methods.

+4
source share
5 answers

Here is a more general solution

 function sz = find_size(m) sz = []; m(f(end), f(end)); function r = f(e) r=[]; sz=[sz e]; end end 

What kind

  • Works for arrays of arrays , arrays of cells and arrays of objects
  • Its time complexity is constant and does not depend on the size of the matrix
  • Does not use MATLAB functions
  • Easy to adapt to larger sizes.
+7
source

For non-empty matrices you can use:

 sz = [sum(m(:,1)|1) sum(m(1,:)|1)]; 

But to cover empty matrices we need more function calls

 sz = sqrt([sum(sum(m*m'|1)) sum(sum(m'*m|1))]); 

or more lines

 n=m&0; n(end+1,end+1)=1; [I,J]=find(n); sz=[I,J]-1; 

Both of them work fine for m=zeros(0,0) , m=zeros(0,10) and m=zeros(10,0) .

+3
source

Incremental indexing and try-catch statement work:

 function sz = find_size(m) sz = [0 0]; isError = false; while ~isError try b = m(sz(1) + 1, :); sz(1) = sz(1) + 1; catch isError = true; end end isError = false; while ~isError try b = m(:, sz(2) + 1); sz(2) = sz(2) + 1; catch isError = true; end end end 
+2
source

A fairly general solution:

 [ sum(~sum(m(:,[]),2)) sum(~sum(m([],:),1)) ] 

It accepts empty matrices (with 0 columns, 0 rows or both), as well as complex , NaN or inf .

It is also very fast : it takes about 22 microseconds for a 1000 Γ— 1000 matrix on my old laptop (a for loop with 1e5 repetitions takes 2.2 seconds, measured with tic , toc ).


How it works:

Keys to handling empty matrices in a unified way:

  • empty indexing (that is, indexing with [] );
  • the fact that summing over an empty dimension yields zeros.

Let r and c be (possibly zero) numbers of rows and columns m . m(:,[]) is an empty vector r Γ— 0. This is true even if r or c are zero. In addition, this empty indexing automatically provides insensitivity to NaN , inf or complex values ​​in m (and probably also takes into account the short calculation time).

Summing this vector r Γ— 0 by its second size ( sum(m(:,[]),2) ), a vector of r Γ— 1 zeros is output. Denial and summation of this vector gives r.

The same procedure is applied to the number of columns, c, by empty indexing in the first dimension and summing over this dimension.

+2
source

The find has a neat option to get the latest K elements:

I = find(X,K,'last') returns no more than the last K indices corresponding to the nonzero entries of the array X`.

To get the size, ask for the last elements k=1 . For instance,

 >> x=zeros(256,4); >> [numRows,numCols] = find(x|x==0, 1, 'last') numRows = 256 numCols = 4 >> numRows0 = size(x,1), numCols0 = size(x,2) numRows0 = 256 numCols0 = 4 

You can use find with a single output syntax that will give you numel :

 >> numEl = find(x|x==0, 1, 'last') numEl = 1024 >> numEl0 = numel(x) numEl0 = 1024 

Another direct but less interesting solution uses whos (thanks for reminding Navan):

 s=whos('x'); s.size 

Finally, there is format debug .

+1
source

Source: https://habr.com/ru/post/1204189/


All Articles