Efficient searching to find the first element of an array meeting a condition
26 ビュー (過去 30 日間)
古いコメントを表示
Hello,
If a vector is given and the task is to find the first element fulfilling a condition then we use the
command 'finb(...,1)'. However, imagine that checking whether any member of my vector meets
the condition is going to be computationally expensive. In such a case the linear search is not a good idea.
An example:
f = @(x) rand(x);
find(f(1:10)>0.5);
Note that in this example it does not take so much time to check the 'condition' (i.e., wether it is bigger than 0.5) but in my actuall problem it is really expensive. So, my question is this: is there an efficient way to find the first element of an array fulfilling a condition?
Thanks in advance!
Babak
0 件のコメント
採用された回答
Florian Bidaud
2023 年 8 月 24 日
編集済み: Florian Bidaud
2023 年 8 月 24 日
Depending on your data, you can split the search into pieces.
Let's say there the probability of your condition being met is 1/10.
Then there is a rather big probability that it is met in the first 10 values of your dataset, therefore you can split the search into vectors of 10 elements.
With your exemple, we could split the search into vectors of 2 because there is one chance out of two that the condition is met.
Provided that the matrix is already stored (Which I guess is the case for you ?), this could give something like the following code.
How to smartly split the data is the tricky part, it is supposing you already have a feeling about the probability of your condition being met.
a = f(1:12);
tic
find(a>0.5,1)
toc
ans =
1
Elapsed time is 0.425812 seconds.
tic
p = 2; % 1/Probability
i = 0;
while true
b = a(i*p+1:(i+1)*p);
I = find(b>0.5,1);
if ~isempty(I)>0
break
end
i = i+1;
end
value = i*p+I
toc
value =
1
Elapsed time is 0.027613 seconds.
Now if we reduce the probability :
tic
find(a>0.999,1)
toc
ans =
1550
Elapsed time is 0.396268 seconds.
tic
p = 1000; % 1/Probability
i = 0;
while true
b = a(i*p+1:(i+1)*p);
I = find(b>0.999,1);
if ~isempty(I)>0
break
end
i = i+1;
end
value = i*p+I
toc
value =
1550
Elapsed time is 0.026435 seconds.
Or even more:
tic
find(a>0.99999,1)
toc
ans =
232137
Elapsed time is 0.387584 seconds.
tic
p = 100000; % 1/Probability
i = 0;
while true
b = a(i*p+1:(i+1)*p);
I = find(b>0.99999,1);
if ~isempty(I)>0
break
end
i = i+1;
end
value = i*p+I
toc
value =
232137
Elapsed time is 0.026697 seconds.
その他の回答 (3 件)
Bruno Luong
2023 年 8 月 24 日
編集済み: Bruno Luong
2023 年 8 月 24 日
just fo the obvious for loop
for i = 1:length(x)
if expensive_check_for_meet_condition(x(i))
ifind = i;
break
end
end
for-loop the most fundamental statement in any programming language often neglected by MATLAB users
6 件のコメント
Bruno Luong
2023 年 8 月 24 日
編集済み: Bruno Luong
2023 年 8 月 24 日
If you know how to sort the array so that the condition meet becomes stronger from start to the end, meaning the expensive_check_for_meet_condition(x) always returns 0s followed by the 1s, a dichotomy (binary) strategy search can be adopted. You cut in half the array check the middle, depending on the test value, you skip the left or right side until your interval reduces to 1 element.
Torsten
2023 年 8 月 24 日
編集済み: Torsten
2023 年 8 月 24 日
"find" will use the "first" option by default which means that the command will return the first occurence of the event and will not search further.
4 件のコメント
Florian Bidaud
2023 年 8 月 24 日
Whislt it's true, the find function will still have to deal with the whole array, consuming unnecessary time if the condition is met early.
C. Rithiya
2023 年 9 月 6 日
a = f(1:12); tic find(a>0.5,1) toc ans = 1 Elapsed time is 0.425812 seconds. tic p = 2; % 1/Probability i = 0; while true b = a(i*p+1:(i+1)*p); I = find(b>0.5,1); if ~isempty(I)>0 break end i = i+1; end value = i*p+I toc value = 1 Elapsed time is 0.027613 seconds.
0 件のコメント
参考
カテゴリ
Help Center および File Exchange で Entering Commands についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!