Bu cevabın altında, fordöngülerden keyfi olarak kaçınmak yerine performansla ilgilendiğinizi açıkladınız .
Aslında, bence fordöngüler muhtemelen burada en performanslı seçenektir. "Yeni" (2015b) JIT motoru tanıtıldığından ( kaynak ) fordöngüler doğal olarak yavaş değildir - aslında dahili olarak optimize edilirler.
O Sen kriter görebilirsiniz mat2cellThomasIsCoding tarafından sunulan seçenek burada çok yavaş ...

Ölçeği daha net hale getirmek için bu çizgiden kurtulursak splitapply, yöntemim oldukça yavaştır, obchardon'un akümülatör seçeneği biraz daha iyidir, ancak en hızlı (ve karşılaştırılabilir) seçenekler arrayfun(Thomas tarafından da önerildiği gibi) veya bir fordöngü kullanır. Bunun çoğu kullanım durumu için kılık değiştirmiş arrayfunbir fordöngü olduğuna dikkat edin , bu şaşırtıcı bir kravat değildir!

Daha forfazla kod okunabilirliği ve en iyi performans için bir döngü kullanmanızı tavsiye ederim .
Düzenle :
Döngünün en hızlı yaklaşım olduğunu varsayarsak, findkomut etrafında bazı optimizasyonlar yapabiliriz .
özellikle
MMantıksal olun . Aşağıdaki çizimde görüldüğü gibi, bu nispeten küçük için daha hızlı olabilir M, ancak büyükler için tür dönüşümünün değişmesi ile daha yavaş olabilir M.
Kullanmak yerine Mdiziyi dizine eklemek için bir mantıksal kullanın . Bu, döngünün en yavaş kısmını ( komut) önler ve tür dönüştürme yükünü ağırlaştırır, bu da onu en hızlı seçenek haline getirir.1:size(M,2)findfind
İşte en iyi performans için önerim:
function A = f_forlooplogicalindexing( M )
M = logical(M);
k = 1:size(M,2);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = k(M(r,:));
end
end
Bunu aşağıdaki karşılaştırmaya ekledim, işte döngü tarzı yaklaşımların karşılaştırması:
Karşılaştırma kodu:
rng(904); % Gives OP example for randi([0,1],3)
p = 2:12;
T = NaN( numel(p), 7 );
for ii = p
N = 2^ii;
M = randi([0,1],N);
fprintf( 'N = 2^%.0f = %.0f\n', log2(N), N );
f1 = @()f_arrayfun( M );
f2 = @()f_mat2cell( M );
f3 = @()f_accumarray( M );
f4 = @()f_splitapply( M );
f5 = @()f_forloop( M );
f6 = @()f_forlooplogical( M );
f7 = @()f_forlooplogicalindexing( M );
T(ii, 1) = timeit( f1 );
T(ii, 2) = timeit( f2 );
T(ii, 3) = timeit( f3 );
T(ii, 4) = timeit( f4 );
T(ii, 5) = timeit( f5 );
T(ii, 6) = timeit( f6 );
T(ii, 7) = timeit( f7 );
end
plot( (2.^p).', T(2:end,:) );
legend( {'arrayfun','mat2cell','accumarray','splitapply','for loop',...
'for loop logical', 'for loop logical + indexing'} );
grid on;
xlabel( 'N, where M = random N*N matrix of 1 or 0' );
ylabel( 'Execution time (s)' );
disp( 'Done' );
function A = f_arrayfun( M )
A = arrayfun(@(r) find(M(r,:)),1:size(M,1),'UniformOutput',false);
end
function A = f_mat2cell( M )
[i,j] = find(M.');
A = mat2cell(i,arrayfun(@(r) sum(j==r),min(j):max(j)));
end
function A = f_accumarray( M )
[val,ind] = ind2sub(size(M),find(M.'));
A = accumarray(ind,val,[],@(x) {x});
end
function A = f_splitapply( M )
[r,c] = find(M);
A = splitapply( @(x) {x}, c, r );
end
function A = f_forloop( M )
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = find(M(r,:));
end
end
function A = f_forlooplogical( M )
M = logical(M);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = find(M(r,:));
end
end
function A = f_forlooplogicalindexing( M )
M = logical(M);
k = 1:size(M,2);
N = size(M,1);
A = cell(N,1);
for r = 1:N
A{r} = k(M(r,:));
end
end
fordöngülerden kaçınmasını mı istiyorsunuz ? Bu sorun için, modern MATLAB sürümlerinde, birfordöngünün en hızlı çözüm olduğundan şüpheleniyorum . Bir performans sorununuz varsa, eski önerilere dayanan çözüm için yanlış yerde aradığınızdan şüpheleniyorum.