Here are three functions that do the job relatively fast.
<< Developer`
ranFirstPos =
Compile[
{{ints, _Integer, 1}, {max, _Integer}},
Block[
{res, ii}
,
ii = 1;
Table[
While[
ints[[ii]] != jj
,
ii++
];
ii
,
{jj, 1, max}
]
]
]
jacobFu[data_] :=
Module[
{cmp, max, dataDD},
cmp = ToPackedArray@ArrayComponents@data;
max = Max@cmp;
dataDD = data[[ranFirstPos[cmp, max]]];
Thread[Rule[dataDD, Range[max]]]
]
Or
kubaImprovedFu[data_] :=
Module[
{cmp}
,
cmp = ArrayComponents[data];
Thread[DeleteDuplicates /@ Rule[data, cmp]]
]
The following alternative does not really answer the question of "how to deal with the result of ArrayComponents
", as it doesn't use ArrayComponents
. This one can be made slightly faster by using System`Utilities`HashTable
rather than an Association
.
jacobFuAssocHash[data_] :=
Module[{jj, assoc},
assoc = Association[];
jj = 1;
Reap[
Do[
If[
! KeyExistsQ[assoc, elem],
assoc[elem] = True;
Sow[elem -> jj];
jj++
]
,
{elem, data}
]
]
][[2, 1]]
Timing comparison
From other posts, we define
kubaFu[data_] :=
Module[
{cmp}
,
cmp = ArrayComponents[data];
Thread[data -> cmp] // DeleteDuplicates
]
goldbergFu[data_] :=
AssociationThread[data, ArrayComponents[data]] // Normal
This gives us
nn = 10^7;
data = FromCharacterCode /@ RandomInteger[{0, 65536 - 1}, nn];
jacobRes = jacobFu[data];//Timing//First
jacobAsHaRes = jacobFuAssocHash[data]; // Timing // First
kubaImRes = kubaImprovedFu[data];//Timing//First
goldbergRes = goldbergFu[data]; // Timing // First
kubaRes = kubaFu[data]; // Timing // First
jacobRes === jacobAsHaRes === kubaImRes === kubaRes === goldbergRes
7.20605
9.41933
10.207
12.3219
21.7913
True
ArrayComponents
?, so usetemp = Flatten@ Trace[ArrayComponents[{"a", "b", "d", "c", "a"}], Replace];
and thenExtract[]
? $\endgroup$"a"
gets1
and"b"
gets2
that"a"
occurs first in your list, or that"a"
occurs before"b"
in the alphabetical order? $\endgroup$