Reputation: 147
I have a vector named 'r' of 201 real values, and another vector named 'knots' of 21 real values. I want to find for each of the 'r' values the index i of the smallest 'knot' value which is greater than the 'r' value. Do I have to do it in a 'for' loop over the 'r' vector, or is there a way I can vectorize the code so I can avoid the for loop?
Upvotes: 0
Views: 55
Reputation: 104474
Nope you can avoid loops. You can use bsxfun
combined with max
. I don't know what shape r
and knots
is in ... if they're row or column vectors, so I'm going to make the code independent of this fact. Take note that what I'm going to write assumes that there is at least one element in r
where a value in knots
is larger than r
. If it isn't, then this code won't work.
Something like this is what I have in mind:
rs = r(:).'; %// Make sure r a row vector '
[knotss,indk] = sort(knots(:)); %// Make sure knots a column vector
%// Make sure that the values are sorted
%// For each value in knots, find all values that are greater than r
check = bsxfun(@gt, knotss, rs);
%// Determine the right indices for each value of knots in sorted array
[~,indc] = max(check, [], 1);
%// Get the original indices
indices = indk(indc);
The first two lines of code make sure that r
is a row vector and knots
is a column vector. We also sort the values in knots
because you want to find the smallest value of knots
that is greater than a value in r
. It allows us to make things more efficient. I also return the actual ordering of knots
because when we find the locations of the smallest value in knots
that is greater than some value r
, we have to refer back to the original order.
Next, the call to bsxfun
creates a 2D Boolean matrix check
. Each column in check
is for each value in knots
. Specifically, each column tells you which values of knots
are greater than a value in r
. For each column, false
means that the corresponding value in r
is not greater than the value in knots
you're looking at and true
is otherwise. Once you find this matrix, you call max
and check over each column independently. When calling max
, only the first time the maximum value is encountered gets returned. Because the Boolean matrix only consists of zeroes and ones, this effectively gives you the first time a true
value is encountered per row, which denotes the smallest possible index that r
can be that is greater than each value in knots
.
You don't need to look at the actual maximum values, but you want the indices of where this maximum occurred, hence the variable indices
is created and is the second output from max
.
Here's a quick example with some test data:
r = [-1 0];
knots = [3 -1 1 0 -3];
Running through the above code, I get this for my indices:
indices =
4
3
This makes sense. The first value of r
is -1, and the value in knots
that is the smallest possible value where knots
is greater than -1 is the value 0, which is in location 4. The second value of r
is 0, and the value in knots
that is the smallest possible value where knots
is greater than 1 is 1, and is in location 3.
Upvotes: 1