Fast - это то, о чем вам следует беспокоиться, а не обязательно полной векторизации. В последних версиях Matlab много умнее об управлении петлями. Если есть компактный векторный способ выражения чего-то, он обычно быстрее, но циклы не должны (всегда) бояться, как раньше.
clc
A = rand(5000)>0.5;
A(1,find(sum(A,1)==0)) = 1; % make sure there is at least one match
% Slow because it is doing too much work
tic;[B,I1]=max(cumsum(A));toc
% Fast because FIND is fast and it runs the inner loop
tic;
I3=zeros(1,5000);
for i=1:5000
I3(i) = find(A(:,i),1,'last');
end
toc;
assert(all(I1==I3));
% Even faster because the JIT in Matlab is smart enough now
tic;
I2=zeros(1,5000);
for i=1:5000
I2(i) = 0;
for j=5000:-1:1
if A(j,i)
I2(i) = j;
break;
end
end
end
toc;
assert(all(I1==I2));
На R2008a, Windows, x64, версия cumsum занимает 0,9 секунды. Версия цикла и поиска занимает 0,02 секунды. Версия с двойным циклом занимает всего 0,001 секунды.
EDIT: Какой из них наиболее быстр, зависит от фактических данных. Двойной цикл занимает 0,05 секунды, когда вы меняете 0,5 на 0,999 (потому что в среднем требуется больше времени на перерыв). cumsum и петля & Находка реализации имеет более последовательные скорости.
EDIT 2: Решение flnud gnovice является умным. К сожалению, на моей тестовой машине это занимает 0,1 секунды, поэтому она намного быстрее, чем cumsum, но медленнее, чем петлевые версии.
Умная идея. К сожалению, это примерно в 5 раз медленнее, чем loop & find. –
Это своего рода результат, который я ожидал: быстрее, чем CUMSUM, но все же медленнее, чем цикл ... хотя он все еще зависит от размера и доли заполнения A (которые OP действительно не определял). – gnovice