Partition a list by count of a number

It is always good to start with System` functions:

Flatten /@ Partition[Split[list, #1 =!= 2 &], UpTo[3]]
{{3, 1, 3, 1, 2, 1, 2, 2}, {2, 3, 2, 3, 2}, {2, 3, 3, 3, 2, 2}, {2}}

alternatively:

Module[{i = 0},
   Sow[#, ⌊ If[# == 2, i++, i]/3 ⌋ ] & /@ list // Reap // Last
 ]

Requires a touch more than just a single call to PartitionBy, but works:

Flatten /@ Partition[GeneralUtilities`PartitionBy[list, # == 2 &], UpTo[3]]

And here is a solution just using PartitionBy as you requested:

i = 1;
GeneralUtilities`PartitionBy[list, 
 If[# == 2, i++; Evaluate@If[i == 3, i = 0; True, False], False] &
]

I think the tricks are make sure the second argument returns True when you want a partition to be created (and False otherwise). And the Evaluate seemed to be required.

Cool idea to use PartitionBy!


Here is a version using SplitBy.

Module[{i = 0}, SplitBy[lst, Floor[1/3 If[# != 2, i, i++]] &]]

(After reading Kuba's second solution more carefully, it turns out that they use the same idea on their second solution, but I figure the SplitBy version is nice to have alongside the Sow/Reap solution.)