How to shift zero in the last column of a matrix

匿名 (未验证) 提交于 2019-12-03 01:58:03

问题:

I have one matrix like below-

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

But I want to place all the 0 at the end of the row, so A should be like-

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

How can I do this? Matlab experts please help me.

回答1:

There you go. Whole matrix, no loops, works even for non-contiguous zeros:

A = [1 1 1 1 1; 0 1 1 1 2; 0 0 1 1 3];  At = A.'; %// It's easier to work with the transpose [~, rows] = sort(At~=0,'descend'); %// This is the important part. %// It sends the zeros to the end of each column cols = repmat(1:size(At,2),size(At,1),1); ind = sub2ind(size(At),rows(:),cols(:)); sol = repmat(NaN,size(At,1),size(At,2)); sol(:) = At(ind); sol = sol.'; %'// undo transpose 

As usual, for Matlab versions that do not support the ~ symbol on function return, change ~ by a dummy variable, for example:

[nada, rows] = sort(At~=0,'descend'); %// This is the important part. 


回答2:

A more generic example:

A = [1 3 0 1 1;      0 1 1 1 2;      0 0 1 1 3]  % Sort columns directly [~,srtcol] = sort(A == 0,2); % Sorted positions  sz  = size(A); pos = bsxfun(@plus, (srtcol-1)*sz(1), (1:sz(1))'); % or use sub2ind 

The result

B = A(pos) B =      1     3     1     1     0      1     1     1     2     0      1     1     3     0     0 


回答3:

there are many ways to do this. one fast way can be easily like this:

a = [1 2 3 4 0 5 7 0];  idx=(find(a==0));  idx =       5     8  b=a;   % save a new copy of the vector b(idx)=[];    % remove zero elements  b =       1     2     3     4     5     7  c=[b zeros(size(idx))]  c =       1     2     3     4     5     7     0     0 

You may modify this code as well.



回答4:

If your zeros are always together, you could use the circshift command. This shifts values in an array by a specified number of places, and wraps values that run off the edge over to the other side. It looks like you would need to do this separately for each row in A, so in your example above you could try:

A(2,:) = circshift(A(2,:), [1 -1]);    % shift the second row one to the left with wrapping A(3,:) = circshift(A(3,:), [1 -2]);    % shift the third row two to the left with wrapping 

In general, if your zeros are always at the front of the row in A, you could try something like:

for ii = 1:size(A,1)                              % iterate over rows in A     numShift = numel(find(A(ii,:) == 0));         % assuming zeros at the front of the row, this is how many times we have to shift the row.     A(ii,:) = circshift(A(ii,:), [1 -numShift]);  % shift it end 


回答5:

Try this (just a fast hack):

for row_k = 1:size(A, 1)    [A_sorted, A_sortmap] = sort(A(row_k, :) == 0, 'ascend');     % update row in A:        A(row_k, :) = A(row_k, A_sortmap); end 

Now optimized for versions of MATLAB not supporting ~ as garbage lhs-identifier.



回答6:

@LuisMendo's answer is inspiring in its elegance, but I couldn't get it to work (perhaps a matlab version thing). The following (based on his answer) worked for me:

Aaux = fliplr(reshape([1:numel(A)],size(A))); Aaux(find(A==0))=0; [Asort iso]=sort(Aaux.',1,'descend'); iso = iso + repmat([0:size(A,1)-1]*size(A,2),size(A,2),1); A=A.'; A(iso).' 


回答7:

I've also asked this question and got a super elegant answer (non of above answers is same) here: Optimize deleting matrix leading zeros in MATLAB



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!