29
$\begingroup$

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$
13
  • 10
    $\begingroup$ Maybe PadRight[{}, 5, {1, 2}]? $\endgroup$
    – Szabolcs
    Nov 11, 2015 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, 2015 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, 2015 at 22:10
  • 7
    $\begingroup$ related/duplicate q/a: Generate cyclic list from a list? $\endgroup$
    – kglr
    Nov 11, 2015 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, 2015 at 23:04

3 Answers 3

29
$\begingroup$

A variation on Szabolcs's suggestion:

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

{1, 2, 1, 2, 1}

$\endgroup$
3
  • 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, 2015 at 21:52
  • $\begingroup$ See Details for ArrayPad $\endgroup$
    – eldo
    Nov 11, 2015 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, 2015 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$
2
  • $\begingroup$ See update ----- $\endgroup$
    – eldo
    Nov 11, 2015 at 21:06
  • $\begingroup$ Excellent! Thanks for addressing that point! (+1) $\endgroup$
    – MarcoB
    Nov 11, 2015 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$
2
  • $\begingroup$ I wonder where that None could come from...? $\endgroup$ Nov 25, 2015 at 11:58
  • $\begingroup$ I dont' know but better skip that ;) CycleValues[None, 5] $\endgroup$
    – Kuba
    Nov 25, 2015 at 12:05

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