I would use:
indicies[x_] := Reap[MapIndexed[Sow[#2, #] &, x]][[2, All, All, 1]]
This will be much faster than repeatedly using Position
, on a long lists with many unique elements. Example:
list = RandomInteger[9999, 10000];
Timing[
result1 =
Function[x, (Flatten@Position[x, #] &) /@ DeleteDuplicates[x]]@list;
]
{3.463, Null}
Timing[
result2 = indicies @ list;
]
{0.031, Null}
result1 === result2
True
TomD
suggested using the newer GatherBy
in place of Sow
and Reap
. This is even faster on long lists with little repetition.
indicies2[x_] := GatherBy[List ~MapIndexed~ x, First][[All, All, 2, 1]]
list2 = RandomInteger[99999, 100000];
Do[indicies @ list2, {10}] // Timing
Do[indicies2 @ list2, {10}] // Timing
{5.523, Null}
{2.823, Null}
Speed is more similar on lists with greater repetition:
list3 = RandomInteger[99, 100000];
Do[indicies @ list3, {10}] // Timing
Do[indicies2 @ list3, {10}] // Timing
{1.716, Null}
{1.607, Null}
If going for pure speed one must recognize that MapIndexed
is not optimized for packed arrays, therefore Range
and Transpose
will be considerably faster in that case:
indicies3[x_] := GatherBy[{x, Range@Length@x}\[Transpose], First][[All, All, 2]]
Do[indicies3 @ list2, {10}] // Timing
{1.981, Null}
Do[indicies3@list3, {10}] // Timing (* big difference here *)
{0.125, Null}