Ordering
and Part
is more efficient than SortBy
and Transpose
and it can also be done in one pass as I will demonstrate.
I create three lists of different type as described in the question:
a = RandomInteger[999, 500];
b = RandomReal[1, 500];
c = CharacterRange["a", "z"] ~RandomChoice~ 500;
I use the timeAvg
function for testing:
SortBy[{a, b, c}\[Transpose], First]\[Transpose] // timeAvg
{a, b, c}[[All, Ordering@a]] // timeAvg
0.00027456
0.000026944
As can be seen second method is more than an order of magnitude faster on this data.
It is noteworthy that these two forms as shown do not perform the same operation because SortBy[list, func]
is not a stable sort. Observe:
lists = {{8, 8, 6, 3, 7},
{"i", "e", "f", "b", "m"},
{"q", "x", "u", "w", "z"}};
SortBy[lists\[Transpose], First]\[Transpose]
lists[[All, Ordering @ First @ lists]]
{{3, 6, 7, 8, 8}, {"b", "f", "m", "e", "i"}, {"w", "u", "z", "x", "q"}}
{{3, 6, 7, 8, 8}, {"b", "f", "m", "i", "e"}, {"w", "u", "z", "q", "x"}}
You can see see that SortBy
has swapped the positions of "i"
/"e"
and "q"
/"x"
in the lists so it is not a minimal reordering. This can be corrected however with a different syntax for SortBy
:
SortBy[lists\[Transpose], {First}]\[Transpose]
{{3, 6, 7, 8, 8}, {"b", "f", "m", "i", "e"}, {"w", "u", "z", "q", "x"}}
This syntax also speeds up SortBy
, but not enough to be competitive with Ordering
:
SortBy[{a, b, c}\[Transpose], {First}]\[Transpose] // timeAvg
0.0001248
Association
. Could anyone implement one? I set up the association:AssociationThread[{2, 3, 1} -> Transpose@{{a, b, c}, {alpha, beta, gamma}}]
, but not sure where to go from there. $\endgroup$