public static IntervalSet Union(IntervalSet a, IntervalSet b) { return(IntersectWith(a, b, (inA, inB) => inA || inB)); }
public static IntervalSet Remove(IntervalSet a, IntervalSet b) { return(IntersectWith(a, b, (inA, inB) => inA && !inB)); }
private static IEnumerable<TextFragment> SplitFragment(TextFragment fragment, List<ITextFragment> processedFragments) { if (processedFragments.Count == 0) { return new List<TextFragment> { fragment }; } var fragmentSet = new IntervalSet( new List<Interval>() { new Interval() { Start = fragment.Start, End = fragment.End + 1 } }); var processedFragmentsSet = new IntervalSet(processedFragments.Select(fr => new Interval() { Start = fr.Start, End = fr.End + 1 }).ToList()); var outputIntervals = IntervalSet.Remove(fragmentSet, processedFragmentsSet); return outputIntervals.Set.Select( i => new TextFragment(i.Start, fragment.Text.Substring(i.Start - fragment.Start, i.End - i.Start))).ToList(); }
// Note that this algorithm won't merge subsequent result subsets. // E.g. result may look like [<2, 3); <3, 5)]. This property is known // and is used by Remove sets operation in ProcessedTextLocationMap. // In case of refactoring/rewriting this function, please consider // modifing new sets generation algorithm in location map. private static IntervalSet IntersectWith(IntervalSet a, IntervalSet b, Func<bool, bool, bool> resultSetPredicate) { var sortedBounds = new SortedList<int, BoundOwner>(); foreach (var i in a.Set) { AddToSortedBounds(sortedBounds, i.Start, true); AddToSortedBounds(sortedBounds, i.End, true); } foreach (var i in b.Set) { AddToSortedBounds(sortedBounds, i.Start, false); AddToSortedBounds(sortedBounds, i.End, false); } var inA = false; var inB = false; var inResult = false; var start = 0; var cList = new List<Interval>(); foreach (var sortedBound in sortedBounds) { if (inResult && start != sortedBound.Key) { cList.Add(new Interval() { Start = start, End = sortedBound.Key }); inResult = false; } if (sortedBound.Value.A) { inA = !inA; } if (sortedBound.Value.B) { inB = !inB; } if (!inResult && resultSetPredicate(inA, inB)) { start = sortedBound.Key; inResult = true; } } return new IntervalSet(cList); }
public static IntervalSet Union(IntervalSet a, IntervalSet b) { return IntersectWith(a, b, (inA, inB) => inA || inB); }
public static IntervalSet Remove(IntervalSet a, IntervalSet b) { return IntersectWith(a, b, (inA, inB) => inA && !inB); }