Star
Star

Reputation: 2299

Modifying sort in Matlab to distinguish between inequalities and equalities

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

Answers (2)

Cris Luengo
Cris Luengo

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

rahnema1
rahnema1

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

Related Questions