In realtà è possibile risolvere questo problema con una semplice moltiplicazione di matrice.
result = M * (1:size(M, 2)).';
3
1
2
1
3
Questo funziona moltiplicando il M x 3 matrice 3 x 1 array in cui gli elementi del 3x1 sono semplicemente [1; 2; 3]
. In breve, per ogni riga di M
, la moltiplicazione a livello di elemento viene eseguita con l'array 3 x 1. Solo gli 1 nella riga di M
generano qualcosa nel risultato. Quindi viene sommato il risultato di questa moltiplicazione di elementi. Poiché hai un solo "1" per riga, il risultato sarà l'indice della colonna in cui si trova 1.
Ad esempio, per la prima riga di M
.
element_wise_multiplication = [0 0 1] .* [1 2 3]
[0, 0, 3]
sum(element_wise_multiplication)
3
Aggiornamento
Sulla base delle soluzioni fornite da @reyryeng e @Luis seguito, ho deciso di eseguire un confronto per vedere come le prestazioni dei vari metodi a confronto.
Per impostare la matrice di test (M
) ho creato una matrice del modulo specificato nella domanda originale e ho variato il numero di righe. Quale colonna ha scelto l'1 in modo casuale usando randi([1 nCols], size(M, 1))
. I tempi di esecuzione sono stati analizzati utilizzando timeit
.
Quando si utilizza M
di tipo double
(impostazione predefinita di MATLAB) si ottengono i seguenti tempi di esecuzione.
Se M
è un logical
, quindi la moltiplicazione matrice subisce un colpo a causa del fatto che esso deve essere convertito in un tipo numerico prima matrice moltiplicazione, mentre gli altri due hanno un po 'di un miglioramento delle prestazioni.
Ecco il codice di prova che ho usato.
sizes = round(linspace(100, 100000, 100));
times = zeros(numel(sizes), 3);
for k = 1:numel(sizes)
M = generateM(sizes(k));
times(k,1) = timeit(@()M * (1:size(M, 2)).');
M = generateM(sizes(k));
times(k,2) = timeit(@()max(M, [], 2), 2);
M = generateM(sizes(k));
times(k,3) = timeit(@()find(M.'), 2);
end
figure
plot(range, times/1000);
legend({'Multiplication', 'Max', 'Find'})
xlabel('Number of rows in M')
ylabel('Execution Time (ms)')
function M = generateM(nRows)
M = zeros(nRows, 3);
col = randi([1 size(M, 2)], 1, size(M, 1));
M(sub2ind(size(M), 1:numel(col), col)) = 1;
end
Grazie mille per la tua risposta molto veloce. È perfetto. – machinery