What's the foo such that foo[{a, b, c}, 2] produces {a, a, b, b, c, c}?
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}
foo[list_, n_] := Catenate @ Table[e, {e, list}, n]
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}