How can I check if Position[i] > Position[j] for two arbitrary elements in a given list?

The problem is that Position[i] returns {{k}} instead of just k, and I don't know how to compare {{k}} and {{l}}.

  • 1
    $\begingroup$ say X contains a position. X[[1,1]] will be the scalar value. You can also goof it with things like Max[X], etc. that will strip the braces. $\endgroup$ – ciao Apr 29 '14 at 4:16

Here's a simple example re: my comment:

afterQ[list_, ele1_, ele2_] := Max[Position[list, ele1]] > Max[Position[list, ele2]]

list = Range[10];
afterQ[list, 3, 4]
afterQ[list, 4, 3]
afterQ[list, 4, 99]
afterQ[list, 99, 4]


So, False if element 1 is not after element 2, True if it is, True if element 1 exists in the list and element 2 does not, False if element 1 is not in the list at all.

You'll want to think about ambiguities here: what if an element is both before and after? Or what if one does not even exist in the list? The above treats the last positions as the arbiter, you may want to do things differently.


I think Simon's method is definitely the way to go provided:

  • You are only concerned with first appearances
  • You know that both elements are in fact present
  • You will not be scanning the list many times

If you are not certain that both elements are present you should scan the list for both of them. You can limit the number of indexes returned by Position using its fourth parameter:

list = Characters @ "xdslkridiatjxzyoedem";

Position[list, #, 1, 1] & /@ {"i", "j"}
{{{7}}, {{12}}}

From this uniform expression you have many options for making a comparison, but the most direct is likely OrderereQ:

OrderedQ @ {{{7}}, {{12}}}

OrderedQ @ {{{12}}, {{7}}}


Perhaps you wish to allow for the possibility that one or both of the elements are missing from the list. You could check like this:

f1 = If[# ~MatchQ~ {{{_}} ..}, OrderedQ @ #, $Failed] &;

f1 @ {{{7}}, {{12}}}
f1 @ {{{12}}, {{7}}}
f1 @ {{}, {{12}}}



I wrote this function to allow a generalization to more than two elements. Combining it with the Position call:

elemOrderedQ[a_List, elem__] :=
  Position[a, #, 1, 1] & /@ {elem} //
    If[# ~MatchQ~ {{{_}} ..}, OrderedQ @ #, $Failed] &


elemOrderedQ[list, "d", "s", "t"]
elemOrderedQ[list, "x", "y", "z"]
elemOrderedQ[list, "s", "t", "u"]



Look-up tables (rule lists)

If you are going to be using this operation on the same list many times (with different elements) you should build a look-up table of elements and positions.

Single positions:

rls = Dispatch @ Thread[# -> Range@Length@#] & @ list

(If there are many duplicates the rule list should be filtered or building the Dispatch table will be slow. That can be done with e.g. GatherBy[rules, First][[All, 1]] where rules is the raw Rules list. Application of the rules will be fast either way.)

Now making comparisons of (first) positions in this list is as simple as this:

"i" > "j" /. rls
"i" > "x" /. rls


It is also very fast. If you have need to compare all positions you can do this:

rls2 = Dispatch @ Reap[MapIndexed[Sow[#2[[1]], #] &, list];, _, Rule][[2]]

With this you can easily pose queries such as:
Are all appearances of "x" before the first appearance of "e"?

Last["x"] < First["e"] /. rls2 // Quiet

I used Quiet here to suppress messages from e.g. Last["x"]. I could also use Unevaluated:

Unevaluated[Last["x"] < First["e"]] /. rls2

An alternative to Position is to scan through the list with Cases and see if j appears first:

jbeforei[list_, i_, j_] := Cases[list, i | j, 1, 1] == {j}

jbeforei[Range[10], 8, 5]
jbeforei[Range[10], 2, 5]

  • $\begingroup$ Lovely method, assuming both elements are present. What is your reason for using a -1 levelspec? $\endgroup$ – Mr.Wizard Apr 30 '14 at 1:31
  • $\begingroup$ @Mr.Wizard, no good reason - just habit and tiredness! $\endgroup$ – Simon Woods Apr 30 '14 at 8:37

Ordering can tell you the position of the smallest and largest values and be used to sort list, e.g.

list = RandomSample[Range[10], 10]


list={7, 4, 10, 8, 6, 5, 1, 9, 3, 2}




{7, 10, 9, 2, 6, 5, 1, 4, 8, 3}

i.e. the smallest element of list is at positon 7 and larges at position 3.

You can sort (in addition to Sort) using:


You can get the position of the smallest 3 elements:

Ordering[list, 3]

or largest 3 elements:

Ordering[list, -3]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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