[英]Vectorizing range setting - 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)
如果你需要一個雙數據類型數組,轉換為double,就像這樣 -
out_double = double(out)
再添加一個混合物! 這個只是使用一個cumsum來生成所有1 - 所以它根本不使用:
運算符 - 它也完全平行: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
以下是如何在不使用循環的情況下構建矩陣。
% 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)
。
此外,如果您的矩陣大小真的很大並且內存成為一個問題,您可能仍然希望堅持循環,但對於“正常大小”,這可能會更快。
每個矢量化都應該有一些懷疑。 如果你實際測量的時間你的循環比給定的答案快,主要是因為你只執行就地寫。
這是另一個可能會更大的尺寸,但我還沒有測試:
tic
myind = [];
for i = 1:5
myind = [myind (5*(i-1))+[l1(i):l2(i)]];
end
A(myind) = 1;
toc
由於線性索引順序,給出轉置的A
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.