Positions of elements in the initial flattened list in a split list
You can use
SplitBy[Range@Length@m1, m1[[#]] &]
There is a complicated trade-off between the speed and compact form in this case, so I have decided to post the version with Range
, which I consider simple enough (comprehensible for new users) and second fast among the conterparts (at least, on my machine).
It is heavily based on @Mr.Wizard solution farsightedly provided by ChrisDegnen, so I do not claim originality:
dynS[p_] := Range @@@ Thread[{Accumulate@p - p + 1, Accumulate@p}]
Method
And after looking at @Mr.Wizard SparseArray
solution I finally realize that we may use Listable
attribute of Range
to get even more compact version (this time I would prefer to keep pure function notation #
). So this is favorite method for me (not mine :)!
dynSP[p_] := Range[# - p + 1, #]& @ Accumulate @ p
Timing benchmarking
I use the long list for benchmarking:
m1 = Flatten[Table[#, # + 1] & /@ RandomInteger[{1, 200}, 10^5]];
Length[m1]
(* 10156647 *)
And packed version later (second timing output in each method).
m1 = Developer`ToPackedArray[m1];
Range[Prepend[# + 1, 1], Append[#, Length @ m1]] &
@ SparseArray[Differences @ m1]["AdjacencyLists"] // Length // RepeatedTiming
(* {0.403, 99530} *)
(* {0.274, 99489} *)
dynSP[Length /@ Split @ m1] // Length // RepeatedTiming
(* {0.476, 99439} *)
(* {0.626, 99439} *)
dynS[Length /@ Split @ m1] // Length // RepeatedTiming
(* {0.506, 99495} *)
(* {0.715, 99489} *)
Internal`PartitionRagged[Range[Length@m1], Length /@ Split@m1] // Length // RepeatedTiming
(* {0.589, 99495} *)
(* {0.78, 99489} *)
dynP[Range@Length@m1, Length /@ Split @ m1] // Length // RepeatedTiming
(* {0.613, 99495} *)
(* {0.83, 99489} *)
Module[{i = 1}, Replace[Split@m1, _ :> i++, {-1}]] // Length // RepeatedTiming
(* {3.845, 99439} *)
(* {4.1, 99439} *)
Module[{i = 0}, Map[++i &, Split[m1], {-1}]] // Length // RepeatedTiming
(* {6.57, 99495} *)
(* {6.85, 99489} *)
SplitBy[Range @ Length @ m1, m1[[#]] &] // Length // RepeatedTiming
(* {24.6, 99495} *)
(* {25., 99489} *)
Note: fastest function with SparseArray
has been added a bit later so its result in terms of length is slightly different. The same is for the Module
with Split
version and my favorite DynSP
.
Perhaps:
s = Split@m1;
Internal`PartitionRagged[Range[Length@m1], Length /@ s]