Skip to content

Instantly share code, notes, and snippets.

@chilversc
Created January 23, 2014 16:09
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/8581320 to your computer and use it in GitHub Desktop.
Save chilversc/8581320 to your computer and use it in GitHub Desktop.
Contiguous segments
#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.ContiguousSegments (IsAdjacent).Dump ();
}
void Sample2 ()
{
var source = new[] {1,2,3,4,5,10,11,12,15,20};
source.ContiguousSegments ((a, b) => a + 1 == 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<IEnumerable<TSource>> ContiguousSegments<TSource> (this IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate)
{
if (source == null)
throw new ArgumentNullException ("source");
if (predicate == null)
throw new ArgumentNullException ("predicate");
return ContiguousSegmentsIterator (source, predicate);
}
private static IEnumerable<IEnumerable<TSource>> ContiguousSegmentsIterator<TSource> (IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate)
{
using (var e = source.GetEnumerator ()) {
if (!e.MoveNext ())
yield break;
var group = new List<TSource> ();
var previous = e.Current;
group.Add (previous);
while (e.MoveNext ()) {
var current = e.Current;
if (!predicate (previous, current)) {
yield return group;
group = new List<TSource> ();
}
group.Add (current);
previous = current;
}
yield return group;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment