Matlab中两个向量之间的值交互作用

Interplay of values between two vectors in Matlab

我有两个等长的向量oc

1
2
o = [-1 -1 -1  0 0 0 1 1 0  0];
c = [-1 -1 -1 -1 0 1 1 1 0 -1];

o代表打开信号(负或pos),c代表关闭信号,假设打开信号之前带有相反的符号。一次只能激活一个信号,因此必须忽略连续性信号。在上面的两个向量中,我的第一个信号在o(1)中,而其对应的关闭信号在c(6)中。这也意味着应该忽略o(2)o(3)中的打开信号,并且在o(7)处找到我的下一个打开信号,并在c(10)处将其相应的关闭,因此导致在o(8)

我正在尝试找到一种矢量化的解决方案,以识别打开/关闭信号的正确序列或索引,以产生以下解决方案示例的内容:

1
2
o = [-1 0 0 0 0 0 1 0 0  0];
c = [ 0 0 0 0 0 1 0 0 0 -1];

我显然可以通过遍历for循环中的每个元素来解决此问题,但是由于我的数据集最多可以包含数百万个元素,而且我发现Matlab中的循环可能相当"昂贵",如果有人解决我的问题的方法是更面向矩阵的,还是通过arrayfun或等同的方法使代码更有效?


您可以使用diff以及一些逻辑运算来获取答案。

1
2
3
4
5
6
o=[-1,-1,-1,0,0,0,1,1,0,0];
oFinal=abs(diff([0,o])).*o;

oFinal=

    -1     0     0     0     0     0     1     0     0     0

诀窍是diff的输出和原始向量o都仅在o中第一次出现该值时才在同一索引处具有非零值(即,第一次出现在o中)链)。因此,通过将它与o逐个元素相乘,即可得到答案。 abs是为了确保不会由于diff的输出而发生符号变化。

c的方法与此类似,我将留给您尝试:)


通常,循环并不比执行其他操作更昂贵,因为其他操作只是将循环隐藏在另一个函数(例如arrayfun)的后面。从您的文本中听起来,您只是选择了错误的算法。您的问题听起来很线性,即O(n),但是您写的关于循环的意思是O(n ^ 2)。拥有数百万个元素的二次运行时不是很好。

您想要的算法是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
open = 0;

for i=1:length(o)
  if (open == 0)
     open=o(i)
  else
     o(i) = 0;
  end
  if (c(i) ~= -open)
     c(i) = 0;
  else
     open = 0;
  end
end

它可能需要一些优化,因为您没有详细描述,例如c和o信号的顺序是什么(例如,如果打开和关闭相同的索引,则首先处理打开或关闭,我的示例代码假定打开),或者信号的顺序是否总是正常,或者是否必须进行一些错误处理-但我想您会想到单循环的想法。