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