У меня есть следующий код. Мне нужно переписать его без циклов. Как я должен это делать?Настройка векторизации - MATLAB
l1 = [1 2 3 2 1];
l2 = [3 4 4 5 4];
A = zeros(5,5);
for i=1:5
A(i, l1(i):l2(i)) = 1;
end
A
У меня есть следующий код. Мне нужно переписать его без циклов. Как я должен это делать?Настройка векторизации - MATLAB
l1 = [1 2 3 2 1];
l2 = [3 4 4 5 4];
A = zeros(5,5);
for i=1:5
A(i, l1(i):l2(i)) = 1;
end
A
Вы можете использовать bsxfun
-
I = 1:5 % Array corresponding to iterator : "for i=1:5"
out = bsxfun(@le,l1(:),I) & bsxfun(@ge,l2(:),I)
Если вам нужен двойной массив типа данных, конвертировать в два раза, как так -
out_double = double(out)
Приятно видеть, что вам не нужна полная координатная сетка, так как bsxfun автоматически расширит 1: 5. Обратите внимание, что этот ответ возвращает логический (что может быть хорошо, но не идентично циклу). –
@DennisJaheruddin Отредактированное решение для покрытия этого требования. – Divakar
Вот как вы могли бы построить матрицу без использования цикла.
% Our starting values
l1 = [1 2 3 2 1];
l2 = [3 4 4 5 4];
% Coordinate grid of the right size (we don't need r, but I keep it there for illustration)
[r,c] = ndgrid(1:5);
% Build the logical index based on our lower and upper bounds on the column indices
idx_l1=bsxfun(@ge,c,l1');
idx_l2=bsxfun(@le,c,l2');
% The result
A = zeros(size(idx_l1));
A(idx_l1&idx_l2)=1
Возможно, вам понадобится что-то вроде [r,c] = ndgrid(1:numel(l1),1:10)
.
Также, если размер вашей матрицы поистине огромен, и память становится проблемой, вы можете в любом случае придерживаться цикла, но для «нормального размера» это может быть быстрее.
Добавить еще один в смесь затем! Это один просто использует cumsum, чтобы генерировать все 1s - так это не использовать оператор :
вообще - это также полностью параллельно: D
l1 = [1 2 3 2 1];
l2 = [3 4 4 5 4];
A = zeros(5,5);
L1 = l1+(1:5)*5-5; %Convert to matrix location index
L2 = l2+(1:5)*5-5; %Convert to matrix location index
A(L1) = 1; %Place 1 in that location
A(L2) = 1; %Place 1 in that location
B = cumsum(A,1) ==1 ; %So fast
Answer = (A|B)'; %Lightning fast
Answer =
1 1 1 0 0
0 1 1 1 0
0 0 1 1 0
0 1 1 1 1
1 1 1 1 0
Там должен быть некоторый скептицизм в каждом векторизации. Если вы измеряете время на самом деле, ваш цикл быстрее, чем заданные ответы, в основном потому, что вы выполняете только запись.
Вот еще один, который, вероятно, получить быстрее для больших размеров, но я не проверял:
tic
myind = [];
for i = 1:5
myind = [myind (5*(i-1))+[l1(i):l2(i)]];
end
A(myind) = 1;
toc
дает транспонированная A
из линейного порядка индексации.
Зачем вам его переписывать? Это слишком медленно? –
: D вы знаете, если вы правильно говорите, это на самом деле хороший вопрос. – GameOfThrows
@ Jørgen Да, это медленно. Фактически размер матрицы огромен, и у меня есть несколько операций, аналогичных описанным выше. Это всего лишь пример, и он упрощен, насколько это возможно. – LNK