8
$\begingroup$

Given an integer, say 20, how can I create the following irregular list of lists?

lst={5,7,3,5};
Range[#]&/@lst;

generates this:

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

I like to have the following list of lists:

{{1,2,3,4,5}, {6,7,8,9,10,11,12}, {13,14,15}, {16,17,18,19,20}}

If the list of lists was a regular sequence, I could use:

Partition[Range[20], 5]] 
$\endgroup$
4
  • 7
    $\begingroup$ TakeList[Range@ Total@(a = {5, 7, 3, 5}), a] $\endgroup$
    – Rabbit
    Commented Apr 20, 2022 at 1:27
  • 2
    $\begingroup$ Or TakeList[Range@Total@#,#]&@lst $\endgroup$
    – user1066
    Commented Apr 20, 2022 at 7:37
  • 3
    $\begingroup$ Range[#]&/@lst; could be Range/@lst; $\endgroup$ Commented Apr 20, 2022 at 10:09
  • 2
    $\begingroup$ @AsukaMinato Or Range@lst! $\endgroup$
    – user1066
    Commented Apr 20, 2022 at 10:28

8 Answers 8

12
$\begingroup$
lst = {5, 7, 3, 5};
  1. First way:

We have

Internal`PartitionRagged[Range@20, lst]
  1. Another one

We have

TakeList[Range@20, lst]

The output is:

list

$\endgroup$
14
$\begingroup$

This is the classic use-case for FoldPairList:

FoldPairList[TakeDrop, Range[20], {5, 7, 3, 5}]

Alternatively, I recently made a resource function for the situation where you want to split at specific positions:

ResourceFunction["SplitAtPositions"][Range[20], {5, 12, 15}, After]
$\endgroup$
1
  • 1
    $\begingroup$ Congrats on the SplitAtPositions. I will keep that in mind :-) $\endgroup$
    – bmf
    Commented Apr 19, 2022 at 21:30
7
$\begingroup$

We create a RangePartition function:

RangePartition[list_List] := MapAt[{#[[1]] + 1, #[[2]]} &, Partition[Flatten[Append[{1}, Accumulate[list]]], 2, 1], Outer[List, Range[2, Length[list]]]]

Also, we create a RangeList function:

RangeList[list_List] := Block[{arraysymb, symb, rangesymb,rangelist},
arraysymb = Array[Subscript[symb, ##] &, 2, 1];
rangesymb = Array[Subscript[symb, ##] &, 2, 1, HoldForm[Range]];
rangelist = 
ReleaseHold[ReplaceAll[Thread[arraysymb -> list]][rangesymb]];
Return[rangelist]]

Then:

Map[RangeList, RangePartition[lst]]

(*{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11, 12}, {13, 14, 15}, {16, 17, 18,19, 20}}*)
$\endgroup$
7
$\begingroup$

Although TakeList is the built-in function to do this, but if you want to do it randomly then a bit of setup would be helpful:

n = 20; (* list length *)
k = 5; (* # parts of list *)
alist = Range[n]
parts = IntegerPartitions[n, {k}]
SeedRandom[1];
TakeList[alist, RandomChoice[parts]]
{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14}, {15, 16, 17, 
  18}, {19, 20}}
$\endgroup$
7
$\begingroup$

Sightly long.

lst={5,7,3,5};
len = Total@lst;
index = Accumulate[lst];
diff = Join[{{1,lst[[1]]}}, Transpose[{index[[;;-2]]+1, index[[2;;]]}]];
(Range@len)[[#1;;#2]]&@@@diff
$\endgroup$
5
$\begingroup$

Starting from your two lines:

lst = {5, 7, 3, 5};
ints = Range[#] & /@ lst;

ints + Flatten[{0, Drop[Accumulate[lst], -1]}]
{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11, 12}, {13, 14, 15}, {16, 17, 18, 19, 20}}
$\endgroup$
4
$\begingroup$

Further alternatives:

ClearAll[f, g, h]

f = FoldList[#2 + Last @ # &] @* Range;

g = Range @ # + Prepend[0] @ Most @ Accumulate @ # &;

h = Total @* Through @* {Range, Prepend[0] @* Most @* Accumulate}

Examples:

f @ lst
{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11, 12}, {13, 14, 15}, {16, 17, 18, 19, 20}}
f @ lst == g @ lst == h @ lst
True
$\endgroup$
1
  • 1
    $\begingroup$ so happy to have seen this answer for two reasons. 1. we did the tenfold way AGAIN and 2. well...it's an answer by you. Do I need more than that? Nicely done!!! $\endgroup$
    – bmf
    Commented Apr 22, 2022 at 14:10
3
$\begingroup$
list = {5, 7, 3, 5};

p = Partition[Prepend[1] @ Most @ Riffle[#, # + 1] & @ Accumulate[list], 2]

{{1, 5}, {6, 12}, {13, 15}, {16, 20}}

Range @@@ p

{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10, 11, 12}, {13, 14, 15}, {16, 17, 18, 19, 20}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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