我有两个长度相等的向量o
和c
:
o = [-1 -1 -1 0 0 0 1 1 0 0];
c = [-1 -1 -1 -1 0 1 1 1 0 -1];
o
表示打开信号(neg或pos),c
表示关闭信号,假设开启信号在其前面有相反的符号。一次只能激活一个信号,因此必须忽略连续信号。在上面的两个向量中,我的第一个信号将在o(1)
中,其相应的结束信号将在c(6)
中找到。这也意味着o(2)
和o(3)
中的开启信号应该被忽略,我的下一个开启信号位于o(7)
,其相应的关闭位于c(10)
,从而导致o(8)
我正在尝试找到一个矢量化解决方案来识别正确的序列或打开/关闭信号的索引,以产生以下解决方案示例的内容:
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
或类似的东西来提高代码的效率?
答案 0 :(得分:1)
您可以使用diff
以及一些逻辑操作来获得答案。
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
相乘,您就得到了答案。 abs
是为了确保由于diff
的输出而未发生符号更改。
c
的方法类似,我会留下让你尝试:)
答案 1 :(得分:0)
通常循环并不像执行一些其他操作那样昂贵,这些操作只是隐藏了另一个函数(例如arrayfun)后面的循环。从你的文字中可以看出你刚刚选择了错误的算法。你的问题听起来很线性,那就是O(n),但你写的是关于循环的循环,这意味着O(n ^ 2)。拥有数百万个元素的二次运行时并不是那么好。
您想要的算法是这样的:
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信号的顺序是什么(例如,如果相同的索引打开和关闭,首先是打开处理或关闭,我的示例代码假定打开),或者信号的顺序是否总是正常,或者是否必须是一些错误处理 - 但我猜你得到了单循环的想法。