14
$\begingroup$

I can define such a foo like this

foo[list_List, n_Integer] := Join @@ Transpose@ConstantArray[list, n]

foo[{3, {1, 4}, 1}, 3]
{3, 3, 3, {1, 4}, {1, 4}, {1, 4}, 1, 1, 1}

...but I could swear that there already is a built-in Mathematica function for this1. I just can't remember it.


1 ...though its signature need not be the same as foo's.

$\endgroup$
  • 4
    $\begingroup$ closely related and stealing here from Simon Woods: Flatten[{#, #, #}, {{2, 1}}] &@{3, 1, 4, 1} $\endgroup$ – user1066 May 18 '17 at 18:06
  • 3
    $\begingroup$ @tomd maybe foo = Table[##] ~Flatten~ {2, 1} & $\endgroup$ – Simon Woods May 18 '17 at 19:06
  • 1
    $\begingroup$ @SimonWoods Very nice! $\endgroup$ – user1066 May 18 '17 at 19:15
11
$\begingroup$

I cannot think of a built-in function that does this more directly than what you wrote, but for the sake of variety you can also use PadRight:

fn[a_List, n_Integer] := PadRight[{a}, {n, Automatic}, a]\[Transpose] // Catenate

fn[{a, b, c}, 4]
{a, a, a, a, b, b, b, b, c, c, c, c}

If n is a power of two then you could Riffle as well:

Nest[Riffle[#, #] &, {a, b, c}, 2]
{a, a, a, a, b, b, b, b, c, c, c, c}

You could even Partition that output to get other values, though that seems rather contrived:

Join @@ Partition[%, 3, 4]
{a, a, a, b, b, b, c, c, c}

Performance

With a small change to fn we can eliminate the Transpose operation.

f2[a_List, n_Integer] :=
  Catenate @ PadRight[#, {Automatic, n}, #] & @ Partition[a, 1]

For both light and heavy replication on packed arrays this tests faster than foo and remains competitive on unpacked arrays.

(* packed *)
foo[Range@1*^6, 5]; // RepeatedTiming
fn[Range@1*^6, 5];  // RepeatedTiming
f2[Range@1*^6, 5];  // RepeatedTiming
{0.3026, Null}

{0.0547, Null}

{0.0663, Null}
(* packed, heavy replication *)
foo[Range@1000, 5000]; // RepeatedTiming
fn[Range@1000, 5000];  // RepeatedTiming
f2[Range@1000, 5000];  // RepeatedTiming
{0.053, Null}

{0.053, Null}

{0.033, Null}
(* unpackable *)
foo[1/Range@1*^6, 5]; // RepeatedTiming
fn[1/Range@1*^6, 5];  // RepeatedTiming
f2[1/Range@1*^6, 5];  // RepeatedTiming
{0.351, Null}

{0.4586, Null}

{0.4945, Null}
foo[1/Range@1000, 5000]; // RepeatedTiming
fn[1/Range@1000, 5000];  // RepeatedTiming
f2[1/Range@1000, 5000];  // RepeatedTiming
{0.0845, Null}

{0.213, Null}

{0.115, Null}
$\endgroup$
9
$\begingroup$
foo[list_, n_] := Catenate @ Table[e, {e, list}, n]
$\endgroup$
7
$\begingroup$

You can also use

f[l_List, n_Integer] := Flatten[Outer[Table, l, {n}, 1], 2]

or

ff[l_List, n_Integer] := Flatten[Thread[Table[l, n]], 1]

Both work:

f[{3, {1, 4}, 1}, 3]
ff[{3, {1, 4}, 1}, 3]

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

$\endgroup$
7
$\begingroup$

In:

f[xs_, n_] := MapThread[Sequence, ConstantArray[xs ,n]];
f[{a,b,c}, 2]

g[xs_, n_] := Sequence @@ (Table[1, n] #) & /@ xs;
g[{a,b,c}, 2]

Out:

{a, a, b, b, c, c}
{a, a, b, b, c, c}
$\endgroup$
6
$\begingroup$

To be readable and intuitive, I suggest:

repeatItems01[lst_List, n_Integer] := Catenate[ConstantArray[#, n] & /@ lst]
$\endgroup$
3
$\begingroup$
ff[v_List, n_Integer] := Last@Reap[Do[Sow[ConstantArray[i, n]], {i, v}]]~Flatten~2;


ff[{3, {1, 4}, 1}, 3]
(* {3, 3, 3, {1, 4}, {1, 4}, {1, 4}, 1, 1, 1} *)

another way:

foo[{}, _] := {};
foo[list_, num_] := Join[ConstantArray[First@list, num], foo[Rest@list, num]];
foo[{3, {1, 4}, 1}, 3]
(* {3, 3, 3, {1, 4}, {1, 4}, {1, 4}, 1, 1, 1} *)
$\endgroup$
2
$\begingroup$

Here's a pretty obscure way:

foo[list_, n_] := ListConvolve[ConstantArray[1, n], Upsample[list, n], 1]

foo[{a, b, c, d}, 3]
{a, a, a, b, b, b, c, c, c, d, d, d}
$\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.