Reputation: 2299
Consider a matrix A
in Matlab of dimension MxN
. I would like your help to construct an algorithm that identifies the rows of A
that are characterised by the same ordering of elements from smallest to largest in a strict sense.
However, I cannot use sort
because sort
does not distinguish between equalities and inequalities.
Let me explain better with an example
clear
A=[1 -2 -4; ...
0 -3 5;
1 1 2
1 2 3
3 3 4
10 7 11];
Notice that:
%A(1,3)<A(1,2)<A(1,1)
%A(2,2)<A(2,1)<A(2,3)
%A(3,1)=A(3,2)<A(3,3)
%A(4,1)<A(4,2)<A(4,3)
%A(5,2)=A(5,1)<A(5,3) %equivalent to A(5,1)=A(5,2)<A(5,3)
%A(6,2)<A(6,1)<A(6,3)
Notice also that: the ordering (in strict sense) of row 1 is different from the ordering of any other row, the ordering of row 2 is the same as the ordering of row 6, the ordering of row 3 is the same as the ordering of row 5, the ordering of row 4 is different from the ordering of any other row.
Hence, I want an algorithm delivering a vector B
of dimension 6x1
characterised by
%B(2)=B(6) and ~= all other elements of B
%B(3)=B(5) and ~= all other elements of B
%B(1)~= all other elements of B
%B(4)~= all other elements of B
The actual numbers put in B
can be totally arbitrary. For example, I would be happy to get
B=[3;...
2;...
1;...
4;...
1;...
2];
Let me show you why sort
does not work
[~,index] = sort(A,2);
[~,~,Bwrong]=unique(index, 'rows');
sort
identifies rows 3,4,5 as having the same ordering because it does not distinguish between equalities and inequalities.
Let me conclude by saying that I would prefer not to use loops because in reality A
is very large.
Upvotes: 2
Views: 45
Reputation: 60514
You want to sort rows based on the set of (in-)equality relations between subsequent elements along each row. This set can be obtained as follows:
s = sign(diff(A,[],2));
The matrix s
contains -1 for >
, 0 for ==
, and 1 for <
. The unique
call proposed by OP will work on the matrix s
:
[~,~,B] = unique(s,'rows');
This answer is very similar to rahnema1's answer, but I think slightly simpler and easier to understand. That solution uses diff
only to find equality, leaving the other ordering relations to the result of sort
. Here we use sign
to convert any positive difference into a +1, and any negative difference into a -1. Thus we can skip the sorting.
It is possible to make it into a one liner:
[~,~,B] = unique(sign(diff(A,[],2)),'rows');
Upvotes: 1
Reputation: 15837
You need also to use the first difference of sorted A
to take into account strict ordering.
[s, idx] = sort(A,2);
d = diff(s,[],2) == 0;
[~,~,B] = unique([idx d],'rows');
Upvotes: 2