从一个给定位置开始查找向量中第一个非零值的位置

时间:2019-05-08 09:17:04

标签: matlab

如果我有一个二进制向量x

x = [1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0];

和位置(线性索引)p

p = 7;

我想找到矢量x中第一个非零值的位置,从位置p开始并向正方向移动:

x = [1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0];
                   ↑                               ↑
           %starting position (7)         %position to find (24)   

可以通过for循环来完成:

for ii = p:length(x)
    if x(ii)~=0
        ind = ii 
        break
    end
end

但是有没有更聪明/更有效的方法来达到相同的结果?

3 个答案:

答案 0 :(得分:3)

您可以从p中选择数组并使用find。

x = [1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0];
p = 7 ; 

iwant = find(x(p:end)>0,1)

答案 1 :(得分:3)

快速计时测试:

  • method1是OP中的循环。

  • method2this answer的固定版本,使用find并复制数组。

  • (我没有添加bwconncomp答案,因为它的速度明显慢了。)

当然,测试结果取决于找到非零元素之前要访问的元素的预期数量以及数组长度nq是第一个非零元素的位置。我总是拿p=10。时间(以秒为单位):

n       q       method1     method2
------  ------  ----------  ----------
1e3     p+5     5.9714e-07  2.8644e-06
1e3     end-5   3.9806e-06  3.3714e-06
1e6     p+5     6.4526e-07  0.0027
1e6     end-5   0.0029      0.0033

因此,find方法的运行时间取决于复制数组和调用find的开销,而循环方法的时间取决于一个人需要访问多少数组元素才能找到第一个非零元素。


测试代码:

N = 1e6;
p = 10;
x = zeros(1,N);
%x(p+5) = 1;
x(end-5) = 1;
timeit(@()method1(x,p))
timeit(@()method2(x,p))


function ind = method1(x,p)
for ii = p:length(x)
    if x(ii)~=0
        ind = ii;
        break
    end
end
end

function ind = method2(x,p)
ind = find(x(p:end),1) + p-1;
end

答案 2 :(得分:2)

您还可以使用 bwconncomp()函数。该函数将为您提供给定数组中的那些位置。职位信息将保存在 islands.PixelIdxList 中。因此,要查找的位置(当然是在p之后)是 ptf 数组的第一个元素:

islands=bwconncomp(x);
positions=[cell2mat(islands.PixelIdxList(:))];
ptf=positions(positions(:)>p);