29
$\begingroup$

This question already has an answer here:

Is there some direct and simple "cyclic Take", sometimes also known as "overtake" in Mathematica. That is, if the take specification runs out of elements, it just cycles back to the beginning (as many times as necessary).

For example, if the functions were named OverTake, then:

OverTake[{1, 2}, 5]
(* {1, 2, 1, 2, 1} *)

(This would be a direct analog of the take functions in the array-processing languages APL and J.)

I can clumsily code a function to do that, but I was hoping for a simple use of something built in.

$\endgroup$

marked as duplicate by Kuba, m_goldberg, user9660, MarcoB, ilian Nov 25 '15 at 15:33

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 10
    $\begingroup$ Maybe PadRight[{}, 5, {1, 2}]? $\endgroup$ – Szabolcs Nov 11 '15 at 20:51
  • 1
    $\begingroup$ @Szabolcs That's brilliant! It also naturally handles the "normal" Take usage when requesting fewer elements than the length of the list. Please post it as an answer! $\endgroup$ – MarcoB Nov 11 '15 at 21:06
  • $\begingroup$ I'm waiting for @Szabolcs to post his comment as answer, since that's the one I'd like to mark (as the simplest). $\endgroup$ – murray Nov 11 '15 at 22:10
  • 7
    $\begingroup$ related/duplicate q/a: Generate cyclic list from a list? $\endgroup$ – kglr Nov 11 '15 at 22:24
  • 1
    $\begingroup$ @kglr I'd like to join murray in asking you to consider undeleting your answer. Although you do reference using "Periodic" with PadRight in the other answer, I don't see why it shouldn't be preserved here as well. $\endgroup$ – MarcoB Nov 11 '15 at 23:04
29
$\begingroup$

A variation on Szabolcs's suggestion:

overTake = PadRight[##, "Periodic"] &;
overTake[{1, 2}, 5]

{1, 2, 1, 2, 1}

$\endgroup$
  • 7
    $\begingroup$ Where did you lean about the "Periodic" argument to PadRight? I'm not seeing it at doc page ref/PadRight. $\endgroup$ – murray Nov 11 '15 at 21:52
  • $\begingroup$ See Details for ArrayPad $\endgroup$ – eldo Nov 11 '15 at 22:10
  • 9
    $\begingroup$ @murray, afaik, the fact that PadRight and PadLeft work with a third argument just like ArrayPad is undocumented. I found out by pure luck -- wishing PadRight worked like ArrayPad, tried it and saw it worked:) $\endgroup$ – kglr Nov 11 '15 at 22:28
14
$\begingroup$
Catenate @ Partition[{1, 2}, 5, 5, 1]

{1, 2, 1, 2, 1}

OverTake[list_, n_] /; Length @ list >= n := Take[list, n]

OverTake[list_, n_] /; Length @ list < n := Catenate @ Partition[list, n, n, 1]

OverTake[Range @ 5, 6]

{1, 2, 3, 4, 5, 1}

OverTake[Range @ 5, 4]

{1, 2, 3, 4}

Update

Faster than solutions with PadRight and Partition

l = 2;
n = 5;
list = Range @ l;

Flatten@ConstantArray[list, IntegerPart[n/l]]~Join~list[[;; Mod[n, l]]]

{1, 2, 1, 2, 1}

Also works for n < l

$\endgroup$
  • $\begingroup$ See update ----- $\endgroup$ – eldo Nov 11 '15 at 21:06
  • $\begingroup$ Excellent! Thanks for addressing that point! (+1) $\endgroup$ – MarcoB Nov 11 '15 at 21:06
3
$\begingroup$

For historical reasons, let me mention the CycleValues function that originates before v6, and can be found in several standard packages. I copy the one from Packages\BarCharts\Charts.m with its description by the dev who included. (If you check however StatisticalPlots.m, it already uses the PadRight version.) Note, that it was meant to handle non-list arguments as well.

(* The following is a useful internal utility function to be
used when you have a list of values that need to be cycled to
some length (as PlotStyle works in assigning styles to lines
in a plot).  The list is the list of values to be cycled, the
integer is the number of elements you want in the final list. *)

CycleValues[{},_] := {}
CycleValues[list_List, n_Integer] := Module[{hold = list},
        While[Length[hold] < n,hold = Join[hold,hold]];
        Take[hold,n] /. None -> {}
    ]
CycleValues[item_,n_] := CycleValues[{item}, n];


CycleValues[0, 5]        (* ==> {0, 0, 0, 0, 0} *)
CycleValues[{1, 2}, 5]   (* ==> {1, 2, 1, 2, 1} *)
$\endgroup$
  • $\begingroup$ I wonder where that None could come from...? $\endgroup$ – István Zachar Nov 25 '15 at 11:58
  • $\begingroup$ I dont' know but better skip that ;) CycleValues[None, 5] $\endgroup$ – Kuba Nov 25 '15 at 12:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.