简体   繁体   中英

Get the first 2 non-zero elements from every row of matrix

I have a matrix A like this:

A = [ 1 0 2 4; 2 3 1 0; 0 0 3 4 ]

A has only unique row elements except zero, and each row has at least 2 non-zero elements.

I want to create a new matrix B from A ,where each row in B contains the first two non-zero elements of the corresponding row in A .

B = [ 1 2 ; 2 3 ; 3 4 ]

It is easy with loops but I need vectorized solution.

Here's a vectorized approach:

A = [1 0 2 4; 2 3 1 0; 0 0 3 4]; % example input
N = 2; % number of wanted nonzeros per row
[~, ind] = sort(~A, 2); % sort each row of A by the logical negation of its values.
% Get the indices of the sorting
ind = ind(:, 1:N); % keep first N columns
B = A((1:size(A,1)).' + (ind-1)*size(A,1)); % generate linear index and use into A

Here is another vectorised approach.

A_bool = A > 0;   A_size = size(A);   A_rows = A_size(1);
A_boolsum = cumsum( A_bool, 2 ) .* A_bool;   % for each row, and at each column,
                                             % count how many nonzero instances
                                             % have occurred up to that column
                                             % (inclusive), and then 'zero' back
                                             % all original zero locations.

[~, ColumnsOfFirsts  ] = max( A_boolsum == 1, [], 2 );
[~, ColumnsOfSeconds ] = max( A_boolsum == 2, [], 2 );

LinearIndicesOfFirsts  = sub2ind( A_size, [1 : A_rows].', ColumnsOfFirsts  );
LinearIndicesOfSeconds = sub2ind( A_size, [1 : A_rows].', ColumnsOfSeconds );

Firsts  = A(LinearIndicesOfFirsts );
Seconds = A(LinearIndicesOfSeconds);

Result = horzcat( Firsts, Seconds )
% Result = 
%    1   2
%    2   3
%    3   4

PS. Matlab / Octave common subset compatible code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM