包含索引的矩阵和列向量,如何不循环进行迭代?

时间:2019-04-08 16:03:04

标签: arrays matlab matrix octave

我有一个大矩阵(500212x7)和一个像下面的列向量

matrix F         vector P
0001011          4
0001101          3
1101100          6
0000110          1
1110000          7

向量包含在矩阵行内考虑的索引。 P(1)指向F(1,4),P(2)指向F(2,3),依此类推。

我想否定P元素所指向的列中F的每一行中的某一位(在同一行中)。

我想到了类似的东西

F(:,P(1)) = ~F(:,P(1));
F(:,P(:)) = ~F(:,P(:));

但是这些情况当然不会产生我期望的结果,因为第一行不会更改P元素,第二行甚至不会让我启动程序,因为完整的向量无法建立索引。 / p>

我的想法是我需要对所有F和P行(“同时”更改/递增)执行此操作,但要采用P元素的

我知道这很容易通过 for 循环实现,但是由于F数组的尺寸很大,因此解决该问题的方法是完全不可接受的。

是否有任何一种Matlab向导可以通过使用矩阵运算来解决此类任务?

3 个答案:

答案 0 :(得分:4)

  

我知道使用for循环很容易实现这一点,但是由于F数组的尺寸很大,因此解决问题的方法是完全不可接受的。

您永远不要做出这样的假设。首先实现循环,然后检查它是否真的对您来说太慢,然后担心优化。

在这里,我正在比较Luis' answer和trival循环:

N = 500212;
F = rand(N,7) > 0.6;
P = randi(7,N,1);

timeit(@()method1(F,P))
timeit(@()method2(F,P))

function F = method1(F,P)
   ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
   F(ind) = ~F(ind); % negate those entries
end

function F = method2(F,P)
   for ii = 1:numel(P)
      F(ii,P(ii)) = ~F(ii,P(ii));
   end
end

Luis的答案的时间为0.0065 s,循环的时间为0.0023 s(MATLAB在线R2019a)。

对于非常大的数组,尤其是是正确的,如果矢量化需要创建中间数组,则循环比矢量化代码要快。内存访问很昂贵,使用更多内存会使代码变慢。

经验教训:不要忽略循环,不要过早尝试优化,也不要在没有比较的情况下进行优化。

答案 1 :(得分:3)

另一种解决方案:

xor( F, 1:7 == P )

说明:

  • 1:7 == P生成一个热阵列。
  • xor将使位保留其值,以0表示,并将其翻转为1。

答案 2 :(得分:2)

不确定它是否符合 wizardry 的要求,但是linear indexing确实可以满足您的要求:

F = [0 0 0 1 0 1 1; 0 0 0 1 1 0 1; 1 1 0 1 1 0 0; 0 0 0 0 1 1 0; 1 1 1 0 0 0 0];
P = [4; 3; 6; 1; 7];
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries