Last active
January 4, 2016 05:49
-
-
Save chilversc/8577648 to your computer and use it in GitHub Desktop.
combining adjacent ranges
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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