10

Given a list (for example, {3, 5}) I would like to make a function genCyclic[n_, list_] which generates a cyclic patterns of list with length n, such that genCyclic[5, {3, 5}] returns {3, 5, 3, 5, 3} or genCyclic[1, {3, 5}] returns {3}.

My current solution is to use ConstantArray to generate the full cycle parts ({3, 5, 3, 5} in the first example) and append the remaining part ({3}) and then Flatten them. I have to say my method seems too ugly.

In my old memory, which is frequently wrong, though, I thought there was a built-in function with this functionality. After spending some time trying to find such a function and failing, I ended up here.

No matter whether there is a built-in function or not, what is the most natural way to implement genCyclic?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
Sungmin
  • 2,285
  • 15
  • 23

2 Answers2

13

Yes there is something quite strightforward:

 genCyclic[n_, list_] := PadRight[{}, n, list]
Kuba
  • 136,707
  • 13
  • 279
  • 740
  • I've always done PadRight[list, n, list], so I guess I've been writing more code than I needed to. +1 – rcollyer Mar 02 '15 at 16:14
  • @rcollyer in case of PadRight[#,n,#]& you can gain one character over {} :) – Kuba Mar 02 '15 at 16:19
  • truthfully, I usually end up using that form, or using single letter variable names, like PadRight[l, n, l], so that I get the benefits without dealing with the pain. – rcollyer Mar 02 '15 at 16:22
  • 2
    @rcollyer Your form is superior because the first element of PadRight needs to be packed if possible, and {} is not packable. See this for example. – Mr.Wizard Jul 29 '15 at 21:27
  • @Mr.Wizard as long as my method is correct somehow. :) – rcollyer Jul 29 '15 at 22:01
10
gcF = PadRight[#2, #, #2] &;
gcF[5, {3, 5}]
(* {3, 5, 3, 5, 3} *)

You can also use "Periodic" for the third argument of PadRight that specifies the padding:

gcF1 = PadRight[#2, #, "Periodic"] &;

As far as I know, this form of PadRight (and PadLeft) is not documented.

Few more alternatives using ArrayPad, Part or ArrayReshape:

gcF2 = ArrayPad[#2, {0, # - Length@#2}, "Periodic"] &;
gcF3 = #2[[Mod[Range@#, Length@#2, 1]]] &;
gcF4 = ArrayReshape[#2, {#1}, #2] &;
gcF5 = ArrayReshape[#2, {#1}, "Periodic"] &;
kglr
  • 394,356
  • 18
  • 477
  • 896