kglr made a very interesting find with Internal`RepetitionFromMultiplicity. However, Internal`RepetitionFromMultiplicity produces unpacked arrays and that tells me that it is not as efficient as it could be.
Here is an attempt to produce a compiled version that also allows for parallelization:
getRepetitionFromMultiplicity =
Compile[{{list, _Integer, 2}, {start, _Integer}, {stop, _Integer}},
Block[{a, x, y, c = 0},
a = Table[0, {i, 1, Total[list[[start ;; stop, 2]]]}];
Do[
x = Compile`GetElement[list, i, 1];
y = Compile`GetElement[list, i, 2];
Do[c++; a[[c]] = x, {i, 1, y}],
{i, start, stop}
];
a
],
CompilationTarget -> "C",
RuntimeAttributes -> {Listable},
Parallelization -> True,
RuntimeOptions -> "Speed"
];
repetitionFromMultiplicity[list_?MatrixQ, jobs_: 1000] :=
Module[{len, starts, stops},
If[jobs <= Length[list],
len = Floor[Length[list]/jobs];
starts = len Range[0, jobs - 1] + 1;
stops = len Range[1, jobs];
stops[[-1]] = Length[list];
Join @@ getRepetitionFromMultiplicity[list, starts, stops]
,
getRepetitionFromMultiplicity[list, 1, Length[list]]
]
]
These are the timings (on a quad core machine):
list = RandomInteger[{3, 12}, {10^7 + 1, 2}];
res2 = Internal`RepetitionFromMultiplicity[list]; // AbsoluteTiming // First
res3 = repetitionFromMultiplicity[list]; // AbsoluteTiming // First
Developer`ToPackedArray@res2 == res3
4.85631
0.586881
True
Join @@ ConstantArray @@@ list: about 50 percent of the timings forConstantArray[#1, #2] & @@@ list // Flattenand about as good asJoin @@MapThread[ConstantArray, Thread[list]]. (+1) – kglr Apr 12 '14 at 11:00Inner[ConstantArray, Sequence @@ Transpose@list, Join]:) – kglr Apr 12 '14 at 11:56