Skip to content

Instantly share code, notes, and snippets.

@chilversc
Last active January 4, 2016 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chilversc/8577648 to your computer and use it in GitHub Desktop.
Save chilversc/8577648 to your computer and use it in GitHub Desktop.
combining adjacent ranges
#define NONEST
void Main()
{
Sample1 ();
Sample2 ();
}
void Sample1 ()
{
var source = new[] {
new Range ( 1, 5),
new Range ( 6, 10),
new Range (12, 15),
new Range (17, 20),
new Range (21, 25),
new Range (26, 30),
new Range (31, 35),
};
source.AggregateSegments (IsAdjacent, (a, b) => new Range (a.Start, b.End)).Dump ();
}
void Sample2 ()
{
var source = new[] {1,2,3,4,5,10,11,12,15,20};
source.AggregateSegments ((a, b) => a + 1 == b, x => new Range (x, x), (a, b) => new Range (a.Start, b)).Dump ();
}
static bool IsAdjacent (Range a, Range b)
{
return a.End + 1 == b.Start;
}
struct Range
{
public readonly int Start;
public readonly int End;
public Range (int start, int end)
{
Start = start;
End = end;
}
}
public static class EnumerableCoda
{
public static IEnumerable<TSource> AggregateSegments<TSource> (this IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate, Func<TSource, TSource, TSource> func)
{
return AggregateSegments (source, predicate, x => x, func);
}
public static IEnumerable<TAccumulate> AggregateSegments<TSource, TAccumulate> (this IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate, Func<TSource, TAccumulate> seed, Func<TAccumulate, TSource, TAccumulate> func)
{
if (source == null)
throw new ArgumentNullException ("source");
if (predicate == null)
throw new ArgumentNullException ("predicate");
if (seed == null)
throw new ArgumentNullException ("seed");
if (func == null)
throw new ArgumentNullException ("func");
return AggregateSegmentsIterator (source, predicate, seed, func);
}
private static IEnumerable<TAccumulate> AggregateSegmentsIterator<TSource, TAccumulate> (IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate, Func<TSource, TAccumulate> seed, Func<TAccumulate, TSource, TAccumulate> func)
{
using (var e = source.GetEnumerator ()) {
if (!e.MoveNext ())
yield break;
var accumulator = seed(e.Current);
var previous = e.Current;
while (e.MoveNext ()) {
var current = e.Current;
if (predicate (previous, current)) {
accumulator = func (accumulator, current);
} else {
yield return accumulator;
accumulator = seed(current);
}
previous = current;
}
yield return accumulator;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment