This issue has largely been mitigated in 10.0.1. New timings for the final test below are:
Needs["GeneralUtilities`"] a = RandomInteger[9, 5*^5]; myPosIdx[a] // AccurateTiming cleanPosIdx[a] // AccurateTiming (* see self-answer below *) PositionIndex[a] // AccurateTiming 0.0149384 0.0149554 0.0545865
Still several times slower here than the readily available alternatives but no longer devastating.
Disconcertingly I have discovered that the new (v10) PositionIndex is horribly slow.
Using Szabolcs's clever GatherBy inversion we can implement our own function for comparison:
myPosIdx[x_] := <|Thread[x[[ #[[All, 1]] ]] -> #]|> & @ GatherBy[Range @ Length @ x, x[[#]] &] Check that its output matches:
RandomChoice[{"a", "b", "c"}, 50]; myPosIdx[%] === PositionIndex[%] True
Check performance in version 10.0.0 under Windows:
a = RandomInteger[99999, 5*^5]; myPosIdx[a] // Timing // First PositionIndex[a] // Timing // First 0.140401 0.920406
Not a good start for the System` function, is it? It gets worse:
a = RandomInteger[999, 5*^5]; myPosIdx[a] // Timing // First PositionIndex[a] // Timing // First 0.031200 2.230814
With fewer unique elements PositionIndex actually gets slower! Does the trend continue?
a = RandomInteger[99, 5*^5]; myPosIdx[a] // Timing // First PositionIndex[a] // Timing // First 0.015600 15.958902
Somewhere someone should be doing a face-palm right about now. Just how bad does it get?
a = RandomInteger[9, 5*^5]; myPosIdx[a] // Timing // First PositionIndex[a] // Timing // First 0.015600 157.295808
Ouch. This has to be a new record for poor computational complexity in a System function. :o



SunPosition is horribly slowrant here and used Wolfram Community. :) $\endgroup$GroupBy, it is a bit slower than yours, but it is nice and succinct:posIdx[x_] := GroupBy[Range@Length@x, (x[[#]] &) -> Identity]. $\endgroup$PositionIndexdoes work correctly with held expressions, whereas this is a bit painful to implement usingGatherBy.a = 1; PositionIndex[Unevaluated[{a, b, c, d}]]$\endgroup$myPosIdxis still slightly faster. $\endgroup$