Immo
Immo

Reputation: 111

Matlab: find first smaller or larger element in an array

I have two arrays of different size A and B. I am comparing A to B and want to find for each element in A the first element in B that is smaller/larger.

I would like to use something like ismember(A,B), except that I am not looking for identical elements. The problem is that 'find' will not work because A and B are not the same size.

I now used a loop but am looking for a more elegant way to program this. Here is the loop:

        for zz=1:length(A)
            tmpmax(zz) = find(B>=A(zz),1);
            tmpmin(zz) = find(B<=A(zz),1,'last');                
        end

Thanks for your suggestions!

Immo

Upvotes: 0

Views: 2041

Answers (2)

user85109
user85109

Reputation:

It depends on how often you will do this, and how large your vectors are. But I would suggest preprocessing the array B. For example, consider the test case:

B = rand(1,10)
B =
  0.82346 0.69483 0.3171 0.95022 0.034446 0.43874 0.38156 0.76552 0.7952 0.18687

We will need to build a cumulative min and max vector. If B is fairly long, there are several ways this might be done.

Bmin = B;
N = inf;
while numel(Bmin) < N
  N = numel(Bmin);
  k = find(diff(Bmin) >= 0);
  Bmin(k+1) = [];
end
Bmax = B;
N = inf;
while numel(Bmax) < N
  N = numel(Bmax);
  k = find(diff(Bmax) <= 0);
  Bmax(k+1) = [];
end

then

Bmin
Bmin =
   0.82346      0.69483       0.3171     0.034446

Bmax
Bmax =
   0.82346      0.95022

(I could have built Bmin and Bmax using a simple for loop too, and it would probably have been faster, but the while loop was more fun to write.)

Now it is simple. In order to find the first element of B that is larger than any given value, use histc on Bmax. And since histc is vectorized, the operation is fast. To do it, look at the second return argument of histc. Or, you could write a vectorized binary search scheme. histc will also solve the minimum element problem, by flipping the order of the elements in Bmin.

If your goal is to find the INDEX of the element, this too is simple enough, by retaining that information when you build Bmin and Bmax.

Upvotes: 1

Gunther Struyf
Gunther Struyf

Reputation: 11168

You can get rid of the loop with:

tmpmin = arrayfun(@(x) find(B>=x,1), A);
tmpmax = arrayfun(@(x) find(B<=x,1,'last'), A );

Upvotes: 1

Related Questions