Finding the values right after and right before some values in a matrix

Hi. Suppose I have the matrix A of size (m*n).
A = [12 44
93 43
128 44
145 41
180 41
220 40
280 40];
also I have the vector V e.g.
V = [13 20 70 90 95 100 102 110 129 130 145 158 170 185 190 200 207 220 270 280 285 290];
I want to find which one of the rows of matrix A based on its first column values is right after and right before the values of vector V, and if one of the values of the first column of matrix A is equal to the values of vector V, I want to find that row.
For example :
A(2,1) is right before V(5) and V(6) and V(7) and V(8)
A(3,1) is right after V(5) and V(6) and V(7) and V(8)
and in case of equality I want to find this
A(4,1) = V(11)
A(5,1) = V(18)
A(7,1) = V(20)
In other words, I want to find exactly which members of vector V are between which members of first column of matrix A with their indices like this :
V(1) and V(2) and V(3) and V(4) is between A(1,1) and A(2,1)
Thanks for your help.

2 Comments

what do you mean by "right before"? If I want to explain it myself I would say 93 is right before 94 (and 94 only!). It is not right before 95!
and right after is the immediate next number, not every number after it.
I am looking for this. For example
V(1) and V(2) and V(3) and V(4) is between A(1,1) and A(2,1)

Sign in to comment.

Answers (2)

res = find(V>A(1,1) & V<A(2,1))
for all elements,
res = arrayfun(@(x,y) find(V>x & V<y), A(1:end-1,1), A(2:end,1),'uni',0)

9 Comments

I need to do this process for A(:,1) not only the first and second row. also I want to show which members of V are between which members of A with their index. Thanks a lot.
that's easy too, check the edited answer. The result you will get as a cell array and to access it,
res{1,1} or res{2,1}
I checked it, but the result is not clear enough. This code is only show the indices of members of vector V and doesn't tell these indices of V are between what values of first column of matrix A. Thanks a lot.
Also this code doesn't show the equality in members of vector V and members of first column of matrix A.
"I checked it, but the result is not clear enough"
It is clear enough and you just don't read it properly to understand it.
res = arrayfun(@(x,y) find(V>x & V<y), A(1:end-1,1), A(2:end,1),'uni',0)
In this arrayfun, I pass A(1:end-1,1) and A(2:end,1), which means, during every iteration, V is checked if it's greater than one element of A and less than the next element. The result is,
res =
6×1 cell array
[1×4 double] %between A(1,1) and A(2,1)
[1×4 double] %between A(2,1) and A(3,1)
[1×2 double] %between A(3,1) and A(4,1)
[1×2 double] %between A(4,1) and A(5,1)
[1×4 double] %between A(5,1) and A(6,1)
[ 19] %between A(6,1) and A(7,1)
And yes, I forgot the give you the code to find equality, it's much simpler,
res_eq = arrayfun(@(x) find(V==x), A(:,1),'uni',0)
Hope this time you understand the result.
Thanks again for your help. I understand the code but I want the output of this code show the indices of V in the form of numbers not in cell arrays and show the values of A in numbers not in the form of
%between A(3,1) and A(4,1)
for example I want the output of this code is a matrix named out, which its first and second members in the first row are the A(1,1) and A(2,1) and the other members in this row are the members of vector V that are lying between the A(1,1) and A(2,1)
out(1,:) = [ 12 93 13 20 70 90];
Thanks a lot.
You see, we can make a matrix if the number of elements is same for each row, if you take res, first two rows have 4 elements and then followed by 2 element rows and again 4 element row, finally just one element.
For this reason only we use cell array.
They are very easy to use. You just need to use {} braces. with the current "res", if you type on the command line,
res{1,1}
you will get the indices.
Anyway, if you need the values of A and V, we can create a cell array called out like,
out = arrayfun(@(x,y) [x, y, V(find(V>x & V<y))], A(1:end-1,1), A(2:end,1),'uni',0)
now if you want to access the contents of first row,
>> out{1,1}
ans =
12 93 13 20 70 90
Thanks a lot. You are right about the "we can make a matrix if the number of elements is same for each row". I just forgot that. This is what I need.
Suppose I want to find that only V(10)=130 is lying between which two members of A(:,1). How can I do this process to have the out cell array like your last code?
And in case of equality how can I have the out cell array like the case of inequality? Thanks a lot.

Sign in to comment.

An alternative method that does not involve loops (or arrayfun) but is not necessary faster than KL's:
comp = abs(A(:, 1) - V);
comp(A(:, 1) > V) = inf;
[~, beforeVidx] = min(comp, [], 2);
isequaltoV = A(:, 1) == V(beforeVidx)';
%for display only:
table(A, beforeVidx, isequaltoV)

4 Comments

Thanks for your help. I run the first line and this error was happened :
comp = abs(A(:, 1) - V);
Error using -
Matrix dimensions must agree.
You're using an old version of matlab (<R2016b). It's always a good idea to mention such things. In pre-R2016b,
comp = bsxfun(@minus, A(:, 1), V);
Also this error was happened.
comp(A(:, 1) > V) = inf;
Error using >
Matrix dimensions must agree.
Same issue, same solution, use bsxfun:
comp(bsxfun(@gt, A(:, 1), V)) = inf;

Sign in to comment.

Asked:

on 6 Nov 2017

Commented:

on 8 Nov 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!