Найти положение первого ненулевого значения в векторе, начиная с одной заданной позиции - PullRequest
3 голосов
/ 08 мая 2019

Если у меня есть двоичный вектор 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 ]

3 голосов
/ 08 мая 2019

Быстрый тест времени:

  • method1 - это цикл в OP.

  • method2 - это фиксированная версия этого ответа с использованием find и копированием массива.

  • (я не добавил bwconncomp ответ, потому что он значительно медленнее).

Результаты теста зависят, конечно, от ожидаемого количества элементов, которые нужно посетить до того, как будет найден ненулевой элемент, а также от длины массива n. q - местоположение первого ненулевого элемента. Я всегда беру 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
3 голосов
/ 08 мая 2019

Вы можете выбрать массив из 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];
p = 7 ; 

iwant = find(x(p:end)>0,1)
2 голосов
/ 08 мая 2019

Вы также можете использовать функцию bwconncomp () . Эта функция даст вам позицию в данном массиве. Информация о позициях будет храниться в Islands.PixelIdxList . Таким образом, позиция для поиска (после p, конечно) является первым элементом массива ptf :

islands=bwconncomp(x);
positions=[cell2mat(islands.PixelIdxList(:))];
ptf=positions(positions(:)>p);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...