如何避免循环减少此代码的计算时间?

bza*_*zak 14 matlab runtime matrix vectorization

如何避免循环减少此代码的计算时间(我的上一个问题的一个解决方案):

我希望找到A(1:3,:)其对应值的列向量M(4,:)不是该单元的一个向量的一部分X(并且显然不等于这些向量之一).如果X非常大,我会寻找快速解决方案.

M = [1007  1007  4044  1007  4044  1007  5002 5002 5002 622 622;
      552   552   300   552   300   552   431  431  431 124 124; 
     2010  2010  1113  2010  1113  2010  1100 1100 1100  88  88;
        7    12    25    15    12    30     2   10   55  32  12];
Run Code Online (Sandbox Code Playgroud)

我直接在这里A:

A = [1007  4044  5002  622;
      552   300   431  124;
     2010  1113  1100   88];
Run Code Online (Sandbox Code Playgroud)

A 包含唯一的列向量 M(1:3,:)

X = {[2 5 68 44],[2 10 55 9 17],[1 55 6 7 8 9],[32 12]};

[~, ~, subs] = unique(M(1:3,:)','rows');

A4 = accumarray(subs(:),M(4,:).',[],@(x) {x});

%// getting a mask of which columns we want
idxC(length(A4)) = false;
for ii = 1:length(A4)
    idxC(ii) = ~any(cellfun(@(x) all(ismember(A4{ii},x)), X));
end
Run Code Online (Sandbox Code Playgroud)

显示我们想要的列

out = A(:,idxC)
Run Code Online (Sandbox Code Playgroud)

结果:

>> out

out =

    1007        4044
     552         300
    2010        1113
Run Code Online (Sandbox Code Playgroud)

列向量[5002;431;1100]被删除,因为[2;10;55]包含在X{2} = [2 10 55 9 17]

列向量[622;124;88]被删除,因为[32 12] = X{4}

另一个例子:与之相同X

    M = [1007  4044  1007  4044  1007  5002 5002 5002 622 622  1007  1007  1007;
          552   300   552   300   552   431  431  431 124 124   552    11    11; 
         2010  1113  2010  1113  2010  1100 1100 1100  88  88  2010    20    20;
           12    25    15    12    30     2   10   55  32  12     7    12     7];

X = {[2 5 68 44],[2 10 55 9 17],[1 55 6 7 8 9],[32 12]};

A = [1007  4044  5002  622  1077;
      552   300   431  124    11;
     2010  1113  1100   88    20];
Run Code Online (Sandbox Code Playgroud)

结果 :(用scmg回答)

如果A根据第一行排序我得到:(正确的结果)

out =

         1007        1007        4044
           11         552         300
           20        2010        1113
Run Code Online (Sandbox Code Playgroud)

如果我不对矩阵进行排序A,我得到:(假结果)

out =

        4044        5002         622
         300         431         124
        1113        1100          88
Run Code Online (Sandbox Code Playgroud)

A(:,4) = [622;124;88]应该删除列向量,因为[32 12] = X{4}.

[5002;431;1100]应该删除列向量,因为[2;10;55]它包含在X{2} = [2 10 55 9 17]

Ika*_*ros 4

Ben Voigt 的答案很好,但这一行for A4i = A4{ii}是导致问题的原因:for 循环不适用于列向量:

%row vector
for i = 1:3
    disp('foo');
end

    foo
    foo
    foo

%column vector
for i = (1:3).'
    disp('foo');
end

    foo
Run Code Online (Sandbox Code Playgroud)

只要尝试一下A4i = A4{ii}.',它应该就能完成你的工作!

现在,如果我们看一下输出:

A(:,idxC) =

    4044        5002
     300         431
    1113        1100
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,最终的结果并不是我们所期望的。

只要unique进行某种排序,子项就不会按照 A 中遇到的顺序编号,而是按照 C 中遇到的顺序编号(已排序):

subs =

 2
 2
 3
 2
 3
 2
 4
 4
 4
 1
 1
Run Code Online (Sandbox Code Playgroud)

因此,您应该通过给出的矩阵而unique不是 A 来获得最终输出

进入

[C, ~, subs] = unique(M(1:3,:)','rows'); 
%% rather than [~, ~, subs] = unique(M(1:3,:)','rows');
Run Code Online (Sandbox Code Playgroud)

然后,要获得最终输出,请输入

>> out = C(idxC,:).'
out =

        1007        4044
         552         300
        2010        1113
Run Code Online (Sandbox Code Playgroud)