5
$\begingroup$

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.

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


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}

| improve this answer | |
$\endgroup$
10
$\begingroup$

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!

| improve this answer | |
$\endgroup$
  • $\begingroup$ One could use "Periodic" for the padding. $\endgroup$ – Karsten 7. Jul 29 '15 at 20:58
  • $\begingroup$ @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. $\endgroup$ – Mr.Wizard Jul 29 '15 at 21:11
  • $\begingroup$ @Karsten Please see the update. If your results do not agree please tell me which version you are using. $\endgroup$ – Mr.Wizard Jul 29 '15 at 21:19
7
$\begingroup$

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.

| improve this answer | |
$\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.