6
$\begingroup$

Consider a list as

list={1,2,3,4};

I can repeat the list n times in this way

listRepeated=Flatten@Table[list, n];

Question 1: Can it be done in a faster way?

I also want to repeat each element n times. For example, for n=3 the above list should become

listElementRepeated={1,1,1,2,2,2,3,3,3,4,4,4};

I can do this in this way

listElementRepeated=Flatten@Gather[listRepeated];

Question 2: Can it be done in a better and faster way?

$\endgroup$
3
$\begingroup$
f1 = Join @@ {#}[[ConstantArray[1, #2]]] &;
f1[Range[4], 3]

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

f2 = Flatten@Transpose[{#}[[ConstantArray[1, #2]]]] &;
f2[Range[4], 3]

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

$\endgroup$
  • $\begingroup$ Performance wise your code is faster in both the cases (Thanks to @Henrik). I wonder why your answer hasn't got many upvotes compared to other answers. $\endgroup$ – Majis Jan 17 '18 at 20:58
  • $\begingroup$ @Majis, i wish i knew why:) $\endgroup$ – kglr Jan 17 '18 at 21:05
6
$\begingroup$

Here's my suggestion:

list = {1, 2, 3, 4};
repeat[list_, n_] := PadRight[list, n Length[list], list]
repeat[list, 3]

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

repeat2[list_, n_] := Sequence @@ ConstantArray[#, n] & /@ list
repeat2[list, 3]

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

repeat solves the first question, and repeat2 solves the second question. Performance-wise repeat is quite a bit slower than Flatten@ConstantArray[list, n], as suggested by Henrik. repeat2 I think should be rather fast. It also has the advantage that I don't apply Flatten or do any such thing at the end, so it will work even if the list elements are themselves lists.

$\endgroup$
  • $\begingroup$ The PadRight method is great! $\endgroup$ – Henrik Schumacher Jan 16 '18 at 17:48
  • $\begingroup$ @HenrikSchumacher Thank you $\endgroup$ – C. E. Jan 16 '18 at 17:56
6
$\begingroup$

Repeated list:

SeedRandom[666];
list = RandomInteger[{1, 100000}, 1000000];
n = 3;

akglr = Join @@ {list}[[ConstantArray[1, n]]]; // RepeatedTiming // First
aCE = PadRight[list, n Length[list], list]; // RepeatedTiming // First
aCarl = Flatten[Outer[Times, ConstantArray[1, n], list]]; // RepeatedTiming // First
aMajis = Flatten@Developer`ToPackedArray[Table[list, n]]; // RepeatedTiming // First
aHenrik = Flatten[ConstantArray[list, n]]; // RepeatedTiming // First
aMajis0 = Flatten@Table[list, n]; // RepeatedTiming // First

aMajis0 == aMajis == aCE == aCarl == aHenrik == akglr1 == akglr2

0.0050

0.0059

0.0087

0.011

0.010

0.21

Duplicating list elements:

bkglr = Flatten@Transpose[{list}[[ConstantArray[1, 3]]]]; // RepeatedTiming // First
bHenrik = Flatten[Transpose[ConstantArray[list, 3]]]; // RepeatedTiming // First
bCarl = Flatten@Outer[Times, list, ConstantArray[1, 3]]; // RepeatedTiming // First
bJason = Fold[Riffle[#1, list, {#2, -1, #2}] &, list, Range[2, n]]; // RepeatedTiming // First

bkglr == bHenrik == bCarl == bJason

0.016

0.016

0.017

0.022

True

Tests ran on a Intel 4980HQ, 16 GB 1600 MHz DDR3L SDRAM.

$\endgroup$
  • $\begingroup$ could you please re-run the first set with akglr = Join @@ {list}[[ConstantArray[1, n]]]; $\endgroup$ – kglr Jan 16 '18 at 20:36
  • $\begingroup$ @kglr Huh? What's going on here? I can understand that Developer`ToPackedArray has some overhead; since I can understand that part works on the ragged array {list} in an instant due to pointers and lazy evaluation. Why on earth does Join take longer on a packed array longer than on an unpacked one? (Btw: Sorry for messing with your code; I switched to Flatten because; it was faster than Join when apllied to the packed array.) $\endgroup$ – Henrik Schumacher Jan 16 '18 at 21:17
  • $\begingroup$ Henrik, thank you. I too am puzzled re Join v Flatten. $\endgroup$ – kglr Jan 16 '18 at 21:22
1
$\begingroup$

This only answers the second part of the question:

Use Fold together with Riffle,

nmax = 10;
Fold[Riffle[#1, list, {#2, -1, #2}] &, list, Range[2, nmax]]
(* {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4} *)
$\endgroup$
1
$\begingroup$

For the second part of the question, perhaps a tiny bit faster than @HenrikSchumacher's answer is to use Outer:

list=RandomInteger[{1,100000},1000000];

r1 = Flatten[Transpose[ConstantArray[list,3]]];//RepeatedTiming
r2 = Flatten @ Outer[Times, list, Developer`ToPackedArray[{1,1,1}]]; //RepeatedTiming

r1 === r2

{0.019, Null}

{0.018, Null}

True

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.