Examples: Suppose the predicate is i == 0
.
Then
- [1] -> [(1)]
- [0] -> []
- [1, 0] -> [(1)]
- [0, 1] -> [(1)]
- [0, 0] -> []
- [1, 1, 0] -> [(1, 1)]
- [1, 0, 1] -> [(1), (1)]
- [1, 1, 0, 0, 1, 0, 1, 1, 1] -> [(1, 1), (1), (1, 1, 1)]
Basically, returning contiguous subsegments where the predicate is false.
I thought this would work
internal static IEnumerable<IEnumerable<T>> PartitionBy<T>(this IEnumerable<T> source, Func<T, bool> condition)
{
IEnumerator<T> mover = source.GetEnumerator();
for (; mover.MoveNext() ; )
{
var chunk = mover.MoveUntil(condition);
if (chunk.Any())
{
yield return chunk;
}
}
}
private static IEnumerable<T> MoveUntil<T>(this IEnumerator<T> mover, Func<T, bool> condition)
{
bool hitCondition = false;
do
{
if (condition(mover.Current))
{
hitCondition = true;
}
else
{
yield return mover.Current;
}
}
while (!hitCondition && mover.MoveNext());
}
but I was seeing that for example with [1, 1, 0] it will return [(1), (1)]. I don't completely understand why. I can make it work if I change
var chunk = mover.MoveUntil(condition);
to have mover.MoveUntil(condition).ToList();
but if possible I'd like to not have to hold any of the subsegments in memory.