How to effiectively substitute the member in list with their order?

I believe this is much faster:

a = {{1020, 3058}, {98, 98}, {599, 600}};
b = Sort@DeleteDuplicates@Flatten@a;
a /. Dispatch@Thread[b -> Range@Length@b]
(* {{4, 5}, {1, 1}, {2, 3}} *)

To wit:

SeedRandom[0]
a = RandomInteger[{1, 1000}, {10000, 2}];
test1 = a /. Dispatch@Thread[b -> Range@Length@b]; // AbsoluteTiming // First
test2 = a /. Thread[b -> Range@Length@b]; // AbsoluteTiming // First
test3 = Cases[a, {x_Integer, y_Integer} :> {Position[b, x][[1, 1]], Position[b, y][[1, 1]]}]; // AbsoluteTiming // First
test4 = a /. Table[b[[i]] -> i, {i, 1, Length@b}]; // AbsoluteTiming // First
(* 0.020565 *)
(* 2.091893 *)
(* 1.335496 *)
(* 1.903513 *)

Just to make sure:

test1 === test2 === test3 === test4
(* True *)

(Since I am stuck on Ver 10.0, I don't have access to RepeatedTiming, so this is the best I can do.)


Perhaps,

With[{u = Union @@ a}, a /. Thread[u -> Range[Length@u]]]

Here is an incremental improvement on existing answers.

march's code as fn0 for reference.

fn1 should work on lists of any shape.

fn2 assumes that your sublists are all the same length.

fn0[a_] := With[{b = Sort@DeleteDuplicates@Flatten@a},
  a /. Dispatch@Thread[b -> Range@Length@b]]

fn1[a_] :=
  a /. AssociationThread[Ordering[#], #] & @ DeleteDuplicates @ Flatten @ a;

fn2[a_] :=
  Module[{flat, asc},
    flat = Flatten@a;
    asc = AssociationThread[Ordering[#], #] & @ DeleteDuplicates @ flat;
    asc ~Lookup~ flat ~Partition~ Length[First @ a]
  ]

a = RandomInteger[1*^6, {500000, 2}];

fn0[a] // RepeatedTiming // First
fn1[a] // RepeatedTiming // First
fn2[a] // RepeatedTiming // First
1.53

1.33

1.09