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.)