I have a list of list: res={{9, 1, 5}, {3, 6, 12}}
I want to change it to res={{5, 1, 3}, {2, 4, 6}}
by following their ordering index such that 1 to 1, 3 to 2, 5 to 3, 6 to 4, 9 to 5, and 12 to 6. How can I achieve this?
4 Answers
$\begingroup$
$\endgroup$
3
res={{9, 1, 5}, {3, 6, 12}};
ArrayReshape[InversePermutation[Ordering[Flatten[res]]],
Dimensions[res]]
(* {{5,1,3},{2,4,6}} *)
-
$\begingroup$ Similarly, alternatively,
res /. Thread[Flatten[res] -> InversePermutation@Ordering@Flatten@res]
. $\endgroup$– marchCommented Oct 19, 2022 at 18:30 -
$\begingroup$ Maybe post it as a separate answer? If I compare the two, I think your solution supports more general shapes, mine only supports arrays. And they behave differently when
res
contains duplicates. $\endgroup$ Commented Oct 19, 2022 at 18:35 -
$\begingroup$
$\endgroup$
1
A method that works for lists with arbitrary structure:
ClearAll[ranks]
ranks = Internal`CopyListStructure[#, Ordering @ Ordering @ Flatten @ #] &;
Examples:
ranks @ {{9, 1, 5}, {3, 6, 12}}
{{5, 1, 3}, {2, 4, 6}}
ranks @ {{9, 1, 5}, 3, {3, 1}, {3, {{{{6}}}, 12}}}
{{8, 1, 6}, 3, {4, 2}, {5, {{{{7}}}, 9}}}
-
$\begingroup$ Hi @kglr! Could you help me on this question: mathematica.stackexchange.com/questions/276775/… $\endgroup$– user88712Commented Dec 3, 2022 at 11:17
$\begingroup$
$\endgroup$
1
Building off of user293787's answer, but possibly more general because it works for ragged arrays as well:
res /. Thread[Flatten[res] -> InversePermutation@Ordering@Flatten@res]
-
$\begingroup$ I think this should be the accepted answer ;) $\endgroup$ Commented Oct 19, 2022 at 18:40
$\begingroup$
$\endgroup$
copy = Internal`CopyListStructure;
rank = Statistics`Library`GetDataRankings;
a = {{9, 1, 5}, {3, 6, 12}};
copy[a, rank @ Flatten @ a]
{{5, 1, 3}, {2, 4, 6}}