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 slow
rant 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$PositionIndex
does work correctly with held expressions, whereas this is a bit painful to implement usingGatherBy
.a = 1; PositionIndex[Unevaluated[{a, b, c, d}]]
$\endgroup$myPosIdx
is still slightly faster. $\endgroup$