Au bas de cette réponse se trouve un code de référence, car vous avez précisé que vous êtes intéressé par les performances plutôt que d'éviter arbitrairement les forboucles.
En fait, je pense que les forboucles sont probablement l'option la plus performante ici. Depuis que le "nouveau" moteur JIT (2015b) a été introduit ( source ), les forboucles ne sont pas intrinsèquement lentes - en fait, elles sont optimisées en interne.
Vous pouvez voir dans le benchmark que l' mat2celloption offerte par ThomasIsCoding ici est très lente ...

Si nous nous débarrassons de cette ligne pour rendre l'échelle plus claire, alors ma splitapplyméthode est assez lente, l' option accumarray d' Obchardon est un peu meilleure, mais les options les plus rapides (et comparables) utilisent soit arrayfun(comme l'a également suggéré Thomas) soit une forboucle. Notez que arrayfunc'est essentiellement une forboucle déguisée pour la plupart des cas d'utilisation, donc ce n'est pas une cravate surprenante!

Je vous recommande d'utiliser une forboucle pour une meilleure lisibilité du code et les meilleures performances.
Modifier :
Si nous supposons que le bouclage est l'approche la plus rapide, nous pouvons faire quelques optimisations autour de la findcommande.
Plus précisément
Rendez Mlogique. Comme le montre le graphique ci-dessous, cela peut être plus rapide pour les relativement petits M, mais plus lent avec le compromis de conversion de type pour les grands M.
Utilisez une logique Mpour indexer un tableau 1:size(M,2)au lieu d'utiliser find. Cela évite la partie la plus lente de la boucle (la findcommande) et l'emporte sur la surcharge de conversion de type, ce qui en fait l'option la plus rapide.
Voici ma recommandation pour de meilleures performances:
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
Je l'ai ajouté au benchmark ci-dessous, voici la comparaison des approches de style boucle:
Code de référence:
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
forboucles? Pour ce problème, avec les versions modernes de MATLAB, je soupçonne fortement qu'uneforboucle est la solution la plus rapide. Si vous avez un problème de performances, je soupçonne que vous cherchez au mauvais endroit la solution basée sur des conseils obsolètes.