# How to imitate list comprehensions for constant arrays?

In Python, ['a'] * 10 generates

['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']


and 10 * [1,2] gives

[1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]


How can I replicate an approximation of this infix syntax?

Update: I'm trying to use InfixNotation from Needs["Notation"] but no luck so far.

• ConstantArray ? – Sektor Jul 29 '15 at 18:49
• The consision of the infix notation is what I'm after. – M.R. Jul 29 '15 at 18:53
• Star[{a_},n_Integer]:= ConstantArray[a,n] – chuy Jul 29 '15 at 19:01
• although I would use a more distinct symbol personally – chuy Jul 29 '15 at 19:03
• Related: (40724), (73174) – Mr.Wizard Jul 29 '15 at 21:23

## 3 Answers

Unevaluated@Sequence[1, 2]~ConstantArray~10


$\$ {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}

Or using Notation

<< Notation

Notation[ParsedBoxWrapper[
RowBox[{
RowBox[{"[", "const_", "]"}], "\[Star]",
"reps_"}]] \[DoubleLongRightArrow] ParsedBoxWrapper[
RowBox[{
RowBox[{"Unevaluated", "@",
RowBox[{"Sequence", "[", "const_", "]"}]}], "~", "ConstantArray", "~",
"reps_"}]]]


Now

[1, 2]\[Star]10


$\$ {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}

Which displays as

Using InfixNotation

pythonStar[const_List, reps_Integer] := ConstantArray[Unevaluated[Sequence @@ const], reps]

InfixNotation[ParsedBoxWrapper["\[Star]"], pythonStar]


Now

{1, 2}\[Star]10


$\$ {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2}

The Notation package is not necessary to use an infix form of \[Star] as that is handled automatically. Also I recommend PadRight for constructing your expression (reference Generating a matrix using sublists A and B n times).

SetAttributes[Star, HoldFirst]

Star[a_List, n_Integer] := PadRight[a, n*Length@a, a]

{1, 2}⋆5    (*  ⋆ is \[Star]  *)

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


\[Star] may be entered with EscstarEsc.

### Performance

Let me demonstrate why I recommend PadRight instead of Sequence in ConstantArray:

foo = Range[100];
n = 250000;

ConstantArray[Unevaluated[Sequence @@ foo], n] // ByteCount // RepeatedTiming
PadRight[foo, Length[foo]*n, foo]              // ByteCount // RepeatedTiming

{1.18, 600000080}

{0.0470, 200000144}


So here PadRight is 25 times faster, and because the output is a packed array it uses one third the memory.

One may be tempted to use "Periodic" padding but unfortunately it is slower:

PadRight[foo, Length[foo]*n, "Periodic"] // ByteCount // RepeatedTiming

{0.4805, 200000144}


Still a packed array and faster than Sequence however!

• One could use "Periodic" for the padding. – Karsten 7. Jul 29 '15 at 20:58
• @Karsten PadRight is much faster than ConstantArray when used well. "Periodic" looks nice but slows down PadRight, but still not so much as to be as slow as ConstantArray. I'll add timings to this post. – Mr.Wizard Jul 29 '15 at 21:11
• @Karsten Please see the update. If your results do not agree please tell me which version you are using. – Mr.Wizard Jul 29 '15 at 21:19

Brief? How about this. Define:

c = ConstantArray;


Now you can get what you want using the infix notation:

"a"~c~7


and

10~c~7


With lists

{1, 2}~c~7


you'll need to Flatten.