Inverse of sorting arrangement

[B,I] = sort(A) output is such that B = A(I). What would be the most efficient way to rather get B and J, such that A = B(J)?

 Accepted Answer

Stephen23
Stephen23 on 4 Oct 2018
Edited: Stephen23 on 27 Jun 2023
Assuming that A is a vector:
[B,I] = sort(A);
[~,J] = sort(I);
B(J)
If you have a matrix/array, then you first need to define what the intended effect is: to sort elements along one dimension (e.g. separately sort each column or row of a matrix) or to sort the rows atomically (i.e. using SORTROWS).

4 Comments

Mohamed Eldin
Mohamed Eldin on 27 Jun 2023
Edited: Mohamed Eldin on 27 Jun 2023
Matlab returns the new matrix according only the first column, why? so the indices will be subtitute regarding the first column values
Stephen23
Stephen23 on 27 Jun 2023
Edited: Stephen23 on 27 Jun 2023
"Matlab returns the new matrix according only the first column, why? so the indices will be subtitute regarding the first column values"
My answer only applies to vector inputs.
The answer to your question is explained in the SORT documentation: "[B,I] = sort(___) also returns a collection of index vectors for any of the previous syntaxes. I is the same size as A and describes the arrangement of the elements of A into B along the sorted dimension" (bold added). This means that if you sort the up/down the columns (default for a matrix) that the indices will give the new row positions of the column elements. This means the indices are 1<=indices<=size(A,1), and if you (incorrectly) interpret them as linear indices then you will get combinations of the first column.
So for matrices ultimately you will need to loop over each row/column, and also decide if you want linear indices or to retain the indices along the dimension along the sorted dimension. Which do you want?
I used the command "sortrows" and it worked perfectly
as in the following example:
[Indata,id] = sortrows(InData,1); % sort InData
[~,ids] = sortrows(id,1); % sort the index
InData_returne = Indata(ids,:); % return InData again
@Mohamed Eldin: you do not need the 2nd SORTROWS, a simple SORT is quite sufficient:
[B,I] = sortrows(A,1);
[~,J] = sort(I);
A = B(J,:);
Also note that if you are only sorting one column instead of SORTROWS you could use indexing & SORT:
[B,I] = sort(A(:,1));

Sign in to comment.

More Answers (2)

Matt J
Matt J on 4 Oct 2018
Edited: Matt J on 4 Oct 2018
[B,I] = sort(A);
J=1:numel(I);
J(I)=J;

2 Comments

Surprisingly, even this works:
[B,I] = sort(A);
J(I) = 1:numel(I);
Yes, but it can have unintended effects if J is a pre-existing variable in the workspace.

Sign in to comment.

If A has distinct elements such as
A = rand(1,10)
A = 1×10
0.0113 0.2350 0.1021 0.4269 0.9673 0.4399 0.3871 0.0288 0.5912 0.1876
a single line command is
[B,~,J] = unique(A);
Check
J
J = 10×1
1 5 3 7 10 8 6 2 9 4
B(J)
ans = 1×10
0.0113 0.2350 0.1021 0.4269 0.9673 0.4399 0.3871 0.0288 0.5912 0.1876

1 Comment

If A has non distinct element, then the above method gives B that is shorter than A (and B has distinct elements) and
B(J) = A
still hold.

Sign in to comment.

Categories

Products

Release

R2018a

Tags

Community Treasure Hunt

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

Start Hunting!