Внизу этого ответа приведен код тестирования, поскольку вы пояснили, что вы заинтересованы в производительности, а не в том, чтобы произвольно избегать forциклов.
На самом деле, я думаю, что forциклы, вероятно, наиболее эффективный вариант здесь. Поскольку был введен «новый» (2015b) механизм JIT ( циклы источника ) forне являются изначально медленными - фактически они оптимизируются внутренне.
Из теста видно, что mat2cellопция, предлагаемая ThomasIsCoding здесь , очень медленная ...

Если мы избавимся от этой линии, чтобы сделать шкалу более четкой, то мой splitapplyметод будет довольно медленным, опция accmarray в obchardon немного лучше, но самые быстрые (и сопоставимые) варианты используют либо 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цикл является самым быстрым решением. Если у вас есть проблемы с производительностью, я подозреваю, что вы ищете не то место для решения, основанного на устаревших советах.