# Replicate sublist in new list

If I have a list of lists $a$ and a list of occurrences of each sublist $n$

a={ {1,1,1}, {2,2,2}, {3,3,3} }
n={1,3,2}


what is the most efficient way to get the following list?

l={{1,1,1},{2,2,2},{2,2,2},{2,2,2},{3,3,3},{3,3,3}}


My current implementation is

l=Flatten[Table[Table[a[[i]],{x,n[[i]]}],{i,Range[Length[n]]}],1]


EDIT

Thank you for the answers!

For the problem as posted, the fastest solution is Catenate[...] from march (inspired by J.M.) at 1.7 10^-5 seconds (AbsoluteTiming), with all other solutions being above 2 10^-5.

If I drastically increase the number of samples I want (for example multiplying n*100), then Catenate[MapThread[Table, {a, List /@ n}]]; takes 1.5 10^-3 seconds and the fastest solution by far is a[[Join @@ MapIndexed[ConstantArray[#2[], #1] &, n]]]; from ubpdqn, at 7.7 10^-5.

In both cases, solutions from garej had intermediate timings.

So I guess the ideal solution depends on the exact problem (size of the array, number of samples, ...) and may or may not have a great impact on the overall performance.

• Flatten[MapThread[ConstantArray, {a, n}], 1]? – J. M. is away Apr 4 '16 at 15:01
• @Delphine If you're using Mma 10, I think Catenate will be about 20% faster than Flatten[..., 1]. – Martin Ender Apr 4 '16 at 15:18

## 3 Answers

a[[Join @@ MapIndexed[ConstantArray[#2[], #1] &, n]]]

• Your solution is actually the fastest. Can you explain a bit what it does? – Delphine Apr 5 '16 at 9:54
• @Delphine MapIndexed uses the index as position in list.ConstantArray just produces the desired number of the position. Join just makes a flat list and then you just use Part ([[...]]) to select the desired outcome. @MartinButtner notes Catenate is faster. This could also be used. – ubpdqn Apr 5 '16 at 10:26
• @ubpdqn, If possible please tell why did not you use of Flatten instead of Join? is there any special reason? – Unbelievable Jun 2 '16 at 19:28
• @Irreversible No special reason. Could use Join. – ubpdqn Jun 2 '16 at 22:35
Table @@@ Transpose[{a, n}] // Catenate


{{1, 1, 1}, {2, 2, 2}, {2, 2, 2}, {2, 2, 2}, {3, 3, 3}, {3, 3, 3}}

Edit Also

Join @@ Table @@@ Thread[{a, n}]

• These are good solutions too, very elegant, but not the fastest. – Delphine Apr 5 '16 at 10:10

From a comment by J.M., what I consider to be the most natural solution:

Flatten[MapThread[ConstantArray, {a, n}], 1];


Via Martin, alternatively do

MapThread[ConstantArray, {a, n}] // Catenate;


You can also do something similar using pure functions and Apply:

ConstantArray[#1, #2] & @@@ Thread[{a, n}] // Catenate;


This is just about as fast as the previous version. You can also get around having to Catenate at the end by using Sequence all along the way, i.e.

Sequence @@ ConstantArray[#1, #2] & @@@ Thread[{a, n}];


but it turns out that this is a little slower (maybe 25% slower).

I tried to come up with a ReplaceAll version, but they were all ten times slower.

The fastest so far seems to be again by J.M. Pre 10.2 version is

Catenate[MapThread[Table, {a, List /@ n}]];


and 10.2 and later is

Catenate[MapThread[Table, {a, n}]];

• Apparently Table[] also works: Catenate[MapThread[Table, {a, n}]] – J. M. is away Apr 4 '16 at 17:37
• @J.M. Perhaps in version newer than V10.0. I had to do Catenate[MapThread[Table, {a, List /@ n}]] to make that work, but it turned out to be 4 times faster than the others! – march Apr 4 '16 at 17:44
• yes, that's the classical syntax for Table[]: Table[1, {5}]. Thus my surprise when I forgot to put in the list for the iterator and it worked anyway. – J. M. is away Apr 4 '16 at 17:46
• I varied the size of the array a and the number of replicates n. It appears this last solution is the fastest, but only if the arrays or the number of replicates are small. – Delphine Apr 5 '16 at 10:08