I am looking for a simple way to group the list-indices of equal elements of a list. Examples:
{1,2,3,3} -> {{1}, {2}, {3,4}}
(the elements at positions 1 and 2 are unique, and those at positions 3 and 4 are equal)
{f,f,g,g,f} -> {{1,2,5}, {3,4}}
(the elements at positions 1,2,5 are equal, and those at positions 3 and 4 are equal)
For now my code is
F[L_] := Values@GroupBy[MapIndexed[List, L], First -> Last, Flatten]
or
G[L_] := GatherBy[MapIndexed[List, A], First][[All, All, 2, 1]]
both of which look very clumsy. Is there a direct way to group? Something along the lines of
GroupBy[L, First -> index]
maybe?
benchmarks
Thanks for all the contributions! Here's a ranking by runtime for specific parameters:
L = RandomInteger[{0, 10^3}, 10^6];
(* Carl's ResourceFunction call (run twice to get timing right) *)
a1 = Values@ResourceFunction["GroupByList"][Range@Length@L, L]; //AbsoluteTiming//First
(* Chris's simplest call *)
a2 = Values@PositionIndex[L]; //AbsoluteTiming//First
(* ubpdqn *)
a3 = Reap[MapIndexed[Sow[#2[[1]], #1] &, L]][[2]]; //AbsoluteTiming//First
(* my second crummy suggestion *)
a4 = GatherBy[MapIndexed[List, L], First][[All, All, 2, 1]]; //AbsoluteTiming//First
(* my first crummy suggestion *)
a5 = Values@GroupBy[MapIndexed[List, L], First -> Last, Flatten]; //AbsoluteTiming//First
(* KennyColnago *)
a6 = Map[SequencePosition[L, {#}][[All, 1]] &, DeleteDuplicates[L]]; //AbsoluteTiming//First
(* OkkesDulgerci *)
a7 = Flatten /@ (Position[L, #] & /@ DeleteDuplicates@L); //AbsoluteTiming//First
(* 0.028881 s for a1 *)
(* 0.086623 s for a2 *)
(* 0.997497 s for a3 *)
(* 1.44011 s for a4 *)
(* 1.8618 s for a5 *)
(* 13.86 s for a6 *)
(* 31.6595 s for a7 *)
a1 == a2 == a3 == a4 == a5 == a6 == a7
(* True *)