是否可以从我的代码中删除for循环?

时间:2013-04-20 05:35:06

标签: matlab vectorization

我想从我的代码中删除嵌套的for循环? 我无法删除它们。

k = 3;    
Data = rand(100,5);    
m = zeros(size(Data));    
N = size(Data,2); % number of features
M = size(Data,1); % number of objects
bound = zeros(N,k+1);

MAX = max(Data);
MIN = min(Data);


for ii = 1:N
    bound(ii,:) = linspace(MIN(ii), MAX(ii), k+1);
end

bound(:,end) = bound(:,end)+eps;

tic;
for ii = 1:M
    for jj=1:N
        for kk=1:k
            if bound(jj,kk)<=Data(ii,jj) && Data(ii,jj)<bound(jj,kk+1)
                m(ii,jj) = kk;
            end
        end
    end
end

3 个答案:

答案 0 :(得分:0)

您可以取消嵌套到一定限度。

乍一看,由于jj索引在嵌套循环中的操作中似乎是统一的,您可以替换

for ii = 1:M
    for jj=1:N
        for kk=1:k
            if bound(jj,kk)<=Data(ii,jj) && Data(ii,jj)<bound(jj,kk+1)
                m(ii,jj) = kk;
            end
        end
    end
end

简单地

for ii = 1:M
    for kk=1:k
        m(ii,(bound(:,kk)<=Data(ii,:)' & Data(ii,:)'<bound(:,kk+1))) = kk;
    end
end

这会给你与以前完全相同的结果。

答案 1 :(得分:0)

由于你的最长循环超过ii=1:M,我们应该优先考虑将这个循环引导到其他循环。最小的循环超过kk=1:k,所以这个可以保持不用担心它太多。您可以使用bsxfun在此类矢量化中产生很好的效果:

for kk = 1:k
    ind = bsxfun(@le, bound(:, kk)', Data) & bsxfun(@gt, bound(:, kk+1)', Data);
    m(ind) = kk;
end

这与上面的代码结果相同。

答案 2 :(得分:0)

另一个替代方案是histc(),专门用于分箱:

for jj = 1:N
   [~, m(:,jj)] =  histc(Data(:,jj),bound(jj,:));
end

此解决方案与bsxfun()相同,但它不是一个非常有意义的比较,因为这里的循环是跨列,而bsxfun跨越边界。因此,根据经验,如果我的列少于边界,我将使用histc(),否则bsxfun()