Skip to content

Instantly share code, notes, and snippets.

@palladin
Created June 15, 2024 11:42
Show Gist options
  • Save palladin/467833b575b07eb733880662675e3ea8 to your computer and use it in GitHub Desktop.
Save palladin/467833b575b07eb733880662675e3ea8 to your computer and use it in GitHub Desktop.
ScanBy
using System;
using System.Linq;
static class Program
{
public static IEnumerable<TAcc> ScanBy<T, TKey, TAcc>(this IEnumerable<T> source, Func<T, TKey> keyFunc, Func<TKey, T, TAcc> seedFunc, Func<TAcc, T, TAcc> aggregateFunc)
{
TAcc acc = default!;
TKey key = default!;
bool pending = false;
EqualityComparer<TKey> comparer = EqualityComparer<TKey>.Default;
foreach (var item in source)
{
if (!pending)
{
key = keyFunc(item);
acc = seedFunc(key, item);
pending = true;
continue;
}
TKey currentKey = keyFunc(item);
if (!comparer.Equals(key, currentKey))
{
yield return acc;
key = currentKey;
acc = seedFunc(key, item);
}
else
acc = aggregateFunc(acc, item);
}
if (pending)
yield return acc;
}
public static void Main()
{
bool[] bits = [true,true,true,false,true,false,false];
// RLE
// (true, 3), (false, 1), (true, 1), (false, 2)
var rle = bits.ScanBy(x => x, (key, item) => (Bit: key, Sum: 1),
(acc, item) => (acc.Bit, acc.Sum + 1));
foreach (var (key, count) in rle)
Console.WriteLine($"({key}, {count})");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment