2016-05-27 11 views
7

Ho una matrice con alcuni valori zero che desidero cancellare.Trasforma una matrice in un vettore impilato dove vengono rimossi tutti gli zeri dopo l'ultimo valore diverso da zero per riga

a=[ 1 2 3 0 0; 1 0 1 3 2; 0 1 2 5 0] 

>>a = 

1  2  3  0  0 
1  0  1  3  2 
0  1  2  5  0 

Tuttavia, desidero cancellare solo quelli dopo l'ultimo valore diverso da zero di ogni riga. Ciò significa che voglio mantenere 1 2 3 dalla prima riga, 1 0 1 3 2 dal secondo e 0 1 2 5 dal terzo.

Desidero quindi memorizzare i valori rimanenti in un vettore. Nel caso dell'esempio questo si tradurrebbe nel vettore

b=[1 2 3 1 0 1 3 2 0 1 2 5] 

L'unico modo che ho capito comporta un ciclo for che vorrei evitare:

b=[]; 
for ii=1:size(a,1) 
    l=max(find(a(ii,:))); 
    b=[b a(ii,1:l)]; 
end 

C'è un modo per vettorizzare questo codice?

+2

Ho modificato il titolo per renderlo più descrittivo per il vostro particolare problema. Rendere il titolo del tuo post "come posso vettorializzare questo codice" non è significativo e non aiuta nessuno. Se qualcun altro viene in questo modo e vede qual è il titolo chi potrebbe avere lo stesso problema, questo sicuramente aiuterà. Ho anche modificato il tuo post per le correzioni generali di grammatica. – rayryeng

risposta

10

Ci sono molti modi possibili per farlo, qui è il mio approccio:

arotate = a' %//rotate the matrix a by 90 degrees 
b=flipud(arotate) %//flips the matrix up and down 
c= flipud(cumsum(b,1)) %//cumulative sum the matrix rows -and then flip it back. 
arotate(c==0)=[] 

arotate = 

    1  2  3  1  0  1  3  2  0  1  2  5 

========================= EDIT =====================

cumSum appena realizzato può avere parametro direzione quindi questo dovrebbe fare:

arotate = a' 
b = cumsum(arotate,1,'reverse') 
arotate(b==0)=[] 

questo parametro direzione non è stato disponibile sulla mia versione 2010b, ma dovrebbe esserci per te se stai usando 2013a o superiore.

6

Ecco un approccio usando bsxfun 's capacità di mascheramento -

M = size(a,2); %// Save size parameter 
at = a.'; %// Transpose input array, to be used for masked extraction 

%// Index IDs of last non-zero for each row when looking from right side 
[~,idx] = max(fliplr(a~=0),[],2); 

%// Create a mask of elements that are to be picked up in a 
%// transposed version of the input array using BSXFUN's broadcasting 
out = at(bsxfun(@le,(1:M)',M+1-idx')) 

corsa del campione (per mostrare l'utilizzo maschera) -

>> a 
a = 
    1  2  3  0  0 
    1  0  1  3  2 
    0  1  2  5  0 
>> M = size(a,2); 
>> at = a.'; 
>> [~,idx] = max(fliplr(a~=0),[],2); 
>> bsxfun(@le,(1:M)',M+1-idx') %// mask to be used on transposed version 
ans = 
    1  1  1 
    1  1  1 
    1  1  1 
    0  1  1 
    0  1  0 
>> at(bsxfun(@le,(1:M)',M+1-idx')).' 
ans = 
    1  2  3  1  0  1  3  2  0  1  2  5 
+0

Divakar, puoi effettivamente smettere di usare '% //' ora :). L'evidenziazione di base di MATLAB è stata ora introdotta, quindi solo "%" renderà i commenti correttamente. Non c'è bisogno di fare '%. '' Se stai facendo la trasposizione come ultima affermazione! – rayryeng

+1

@rayryeng wow, sì, ho notato che qualcosa era fuori haha. Bello! Grazie per avermelo fatto notare :) – Divakar

+0

Il missaggio di '' 'e' .'' è intenzionale? Vedo che lo fai ogni volta che sai che una matrice contiene numeri interi (cioè dimensioni e indici). –

Problemi correlati