4
$\begingroup$

This question already has an answer here:

How can I computationally efficiently sort a list so as to return the positions and not the actual values at those positions (which SortBy does)?

$\endgroup$

marked as duplicate by Alexey Popkov, user9660, m_goldberg, MarcoB, Mr.Wizard Jun 5 '16 at 19:31

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 3
    $\begingroup$ Are you talking about Ordering? $\endgroup$ – Kuba Jan 20 '16 at 9:05
  • $\begingroup$ yes, I didn't notice that function. Confused with R. Thanks! $\endgroup$ – Al Guy Jan 20 '16 at 9:15
  • 1
    $\begingroup$ @Kuba I guess, rather about OrderingBy (which does not yet exist as built-in). $\endgroup$ – Leonid Shifrin Jan 20 '16 at 9:47
  • 1
    $\begingroup$ @JasonB Speed. The way Mathematica evaluator works, SortBy is often vastly faster. The reason is a bit long to explain, but here is one place to look at, and here is another. It could've been discussed also here on this site, but I can't recall where. $\endgroup$ – Leonid Shifrin Jan 20 '16 at 10:30
  • 1
    $\begingroup$ here. I can see that SortBy is faster, and so a true implementation of OrderingBy probably would be faster than Ordering as written below. $\endgroup$ – Jason B. Jan 20 '16 at 10:32
9
$\begingroup$

There were comments about the lack of an OrderingBy function, and for this I'll quote Szabolcs

I think that OrderingBy is not necessary. It it were to be analogous to SortBy then OrderingBy[list, f] would give exactly the same output as Ordering[f /@ list], which can even be changed to

So we can just write

orderingBy[list_, f_] := Ordering[f /@ list];
orderingBy[f_] := Ordering[f /@ #] &;

and apply it to a list,

orderingBy[{{1, 2, 3}, {2, 3, 1}, {3, 1, 2}, {2, 2}}, Total]
orderingBy[{{1, 2, 3}, {2, 3, 1}, {3, 1, 2}, {2, 2}}, Rest]
orderingBy[{{1, 2, 3}, {2, 3, 1}, {3, 1, 2}, {2, 2}}, Last]
(* {4, 1, 2, 3} *)
(* {4, 3, 1, 2} *)
(* {2, 3, 4, 1} *)

or use it in the operator form

orderingBy[Last]@{{1, 2, 3}, {2, 3, 1}, {3, 1, 2}, {2, 2}}
(* {2, 3, 4, 1} *)
$\endgroup$
  • $\begingroup$ To save the next person who tries this solution some time: This function does not sort for tie breakers as would be the expected behavior for such a orderingBy function (Compare to the behavior of SortBy). So please read the answer by Mr. Wizard before applying this solution. Of course a perfect solution is also already given by Leonid Shifrin at the linked question. $\endgroup$ – Kvothe Sep 25 '18 at 14:11
5
$\begingroup$

I think this should be marked as a duplicate of:

The method Jason posted is not equivalent to SortBy unless one is using the stable form, because no tie-breaking using the original expression is performed. Consider:

a = {{1, 7, 0}, {1, 4}, {1, 2}, {2}};

b = SortBy[a, First]
Ordering[First /@ a]
{{1, 2}, {1, 4}, {1, 7, 0}, {2}}

{1, 2, 3, 4}

Jason's method indicates that the elements are already in order, but SortBy reorders significantly. To match the default behavior of SortBy we could instead use an explicit Identity with my orderingBy function:

orderingBy[a, {First, Identity}]
a[[%]] === b
{3, 2, 1, 4}

True

To handle the default tie-break implicitly we could add a definition:

orderingBy[lst_List, sfn_] := orderingBy[lst, {sfn, Identity}]

And in v10 fashion an operator form:

orderingBy[fns_][lst_List] := orderingBy[lst, fns]

Now:

a // orderingBy[First]
{3, 2, 1, 4}
$\endgroup$
  • $\begingroup$ Right you are, I think that makes my answer just plain wrong. Thanks for pointing it out, it isn't letting me delete the answer though $\endgroup$ – Jason B. Jun 6 '16 at 0:21
  • $\begingroup$ @Jason That is probably because it is the Accepted answer. I don't think your answer is wrong really, just incomplete. Your method is elegant where applicable and I did not intend to denigrate it. Rather I wanted to make the case that this question is a duplicate of the one referenced, and I think I was successful as four people joined me in voting that way. $\endgroup$ – Mr.Wizard Jun 6 '16 at 23:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.