# How to shift all the non-zero elements of a matrix to the right of the matrix?

3 views (last 30 days)
Devika Waghela on 5 May 2021
Commented: Adam Danz on 5 May 2021
I have a matrix like
1 2 3 0 0 1 2 0
0 0 1 2 3 0 0 0
1 0 0 1 2 3 1 2
I want to shift all the non-zero elements to the right of the matrix. The answer should be
0 0 0 1 2 3 1 2
0 0 0 0 0 1 2 3
0 0 1 1 2 3 1 2
Dyuman Joshi on 5 May 2021
What have you tried yet?

Adam Danz on 5 May 2021
m = [1 2 3 0 0 1 2 0
0 0 1 2 3 0 0 0
1 0 0 1 2 3 1 2];
mSort = cell2mat(cellfun(@(v){[v(v==0),v(v~=0)]},mat2cell(m,ones(size(m,1),1),size(m,2))))
mSort = 3×8
0 0 0 1 2 3 1 2 0 0 0 0 0 1 2 3 0 0 1 1 2 3 1 2

the cyclist on 5 May 2021
Edited: the cyclist on 5 May 2021
% The original data
M = [1 2 3 0 0 1 2 0
0 0 1 2 3 0 0 0
1 0 0 1 2 3 1 2];
% Preallocate the matrix (which also effectively fills in all the zeros)
M_sorted = zeros(size(M));
% For each row of M, identify the non-zero elements, and fill them into the
% end of each corresponding row
for nm = 1:size(M,1)
nonZeroThisRow = M(nm,M(nm,:)~=0);
M_sorted(nm,end-numel(nonZeroThisRow)+1:end) = nonZeroThisRow;
end
% Display the result
disp(M_sorted)
0 0 0 1 2 3 1 2 0 0 0 0 0 1 2 3 0 0 1 1 2 3 1 2

Sean de Wolski on 5 May 2021
Edited: Sean de Wolski on 5 May 2021
Without loop or cells:
x = [1 2 3 0 0 1 2 0
0 0 1 2 3 0 0 0
1 0 0 1 2 3 1 2];
xt = x.';
sxr = sort(logical(xt), 1, "ascend");
[row, col] = find(sxr);
m = accumarray([col row], nonzeros(xt), size(x))
m = 3×8
0 0 0 1 2 3 1 2 0 0 0 0 0 1 2 3 0 0 1 1 2 3 1 2
Adam Danz on 5 May 2021
+1 nice one!