Given something like that at work and depending on the usage/location I'd suggest making Interval generic:
public class Interval<T> where T : IComparable<T>{ public T Start { get; set; } public T End { get; set; }}
Also it would make sense to stream through resulting interval instead of holding 2 copies of all of them in memory.In this case Merge would have a different signature
IEnumerable<Interval<T>> Merge<T>(IEnumerable<Interval<T>> intervals) where T : IComparable<T>
and inside the body of that method you can use yield return
and yield break
operator to enumerate resulting intervals.Method would look like
IEnumerable<Interval<T>> Merge<T>(IEnumerable<Interval<T>> intervals) where T : IComparable<T>{ if(intervals == null) yield break; Interval<T> currentMerged = null; foreach (var interval in intervals.OrderBy(_ => _.Start)) { if (currentMerged == null) { currentMerged = interval; continue; } if (currentMerged.End.CompareTo(interval.Start) < 0) { yield return currentMerged; currentMerged = interval; continue; } if (currentMerged.End.CompareTo(interval.End) < 0) currentMerged.End = interval.End; } if(currentMerged != null) yield return currentMerged;}