У нижній частині цієї відповіді є деякий код бенчмаркінгу, оскільки ви уточнили, що вас цікавить ефективність, а не довільно уникати forциклів.
Насправді, я думаю, forпетлі - це, мабуть, найефективніший варіант тут. З моменту впровадження «нового» (2015b) двигуна JIT ( джерело )for петлі по суті не повільні - адже вони оптимізовані всередині країни.
З еталону видно, що mat2cellопція, запропонована ThomasIsCoding тут , дуже повільна ...

Якщо ми позбудемося цього рядка, щоб зробити splitapplyясність чіткішою, то мій метод досить повільний, варіант обхардона акумуляторного варіанту трохи кращий, але найшвидші (і порівнянні) варіанти або використовуються arrayfun(як це запропонував Томас), або forцикл. Зауважте, що arrayfunв основному це forпетля, замаскована для більшості випадків використання, тому це не дивно, що це стосується!

Я рекомендую вам використовувати forцикл для підвищення читабельності коду та найкращої продуктивності.
Редагувати :
Якщо припустити, що циклічне підключення - це найшвидший підхід, ми можемо зробити деякі оптимізації навколо findкоманди.
Конкретно
Зробити Mлогічним. Як показано на рисунку нижче, це може бути швидше відносно невеликим M, але повільніше, коли компроміс конверсії типів для великихM .
Використовуйте логічне, Mщоб індексувати масив, 1:size(M,2)а не використовувати find. Це дозволяє уникнути найповільнішої частини циклу ( findкоманда) і переважає накладні перетворення типів, роблячи це найшвидшим варіантом.
Ось моя рекомендація щодо найкращих показників:
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
Я додав це до еталону нижче, ось порівняння підходів у стилі циклу:
Код бенчмаркінгу:
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
forциклів? З цієї проблеми, в сучасних версіях MATLAB, я сильно підозрюю, щоforцикл є найшвидшим рішенням. Якщо у вас є проблеми з роботою, я підозрюю, що ви шукаєте рішення в неправильному місці на основі застарілих порад.