public bool TryGetValue(TKey key, out TValue value) { var index = RangeOperations <TKey> .BinarySearch(this.Keys, key); if (index >= 0) { value = this.items[index].Value; return(true); } value = default; return(false); }
/// <summary>Adds a new value at the specified key range.</summary> /// <exception cref="ArgumentOutOfRangeException">Thrown when the range overlaps an existing range of the dictionary.</exception> /// <param name="range">The key range.</param> /// <param name="value">The value.</param> /// <remarks>This operation takes O(log n) time, where n is the number of range key and value pairs)</remarks> public void Add(Range <TKey> range, TValue value) { var left = ~RangeOperations <TKey> .BinarySearch(this.Keys, range.From); var right = ~RangeOperations <TKey> .BinarySearch(this.Keys, range.To); if ((left < 0) || (right < 0) || (left != right)) { throw new ArgumentOutOfRangeException(nameof(range), "The range overlaps an existing range"); } this.items.Insert(left, new KeyValuePair <Range <TKey>, TValue>(range, value)); this.MergeIfAdjacent(left, left + 1); this.MergeIfAdjacent(left - 1, left); }
public void Difference(char[] expected, char from1, char to1, char from2, char to2) { var range1 = Range <char> .Create(from1, to1); RangeSet <char> set1 = range1; var range2 = Range <char> .Create(from2, to2); RangeSet <char> set2 = range2; Assert.Equal(expected, RangeOperations <char> .Difference(set1, set2).Expand()); Assert.Equal(expected, (set1 ^ set2).Expand()); Assert.Equal(expected, (range1 ^ range2).Expand()); Assert.Equal(expected, (set1 ^ range2).Expand()); Assert.Equal(expected, (range1 ^ set2).Expand()); }
public void Subtract(char[] expected, char from1, char to1, char from2, char to2) { var range1 = Range <char> .Create(from1, to1); RangeSet <char> set1 = range1; var range2 = Range <char> .Create(from2, to2); RangeSet <char> set2 = range2; Assert.Equal(expected, RangeOperations <char> .Subtract(set1, set2).Expand()); Assert.Equal(expected, (set1 - set2).Expand()); Assert.Equal(expected, (range1 - range2).Expand()); Assert.Equal(expected, (set1 - range2).Expand()); Assert.Equal(expected, (range1 - set2).Expand()); }
public void Union(char[] expected, char from1, char to1, char from2, char to2) { var range1 = Range <char> .Create(from1, to1); RangeSet <char> set1 = range1; var range2 = Range <char> .Create(from2, to2); RangeSet <char> set2 = range2; Assert.Equal(expected, RangeOperations <char> .Union(set1, set2).Expand()); Assert.Equal(expected, new RangeSet <char>((IEnumerable <Range <char> >)(new[] { range1, range2 })).Expand()); Assert.Equal(expected, (set1 | set2).Expand()); Assert.Equal(expected, (range1 | range2).Expand()); Assert.Equal(expected, (set1 | range2).Expand()); Assert.Equal(expected, (range1 | set2).Expand()); }
public IEnumerable <KeyValuePair <Range <TKey>, TValue> > Slice(Range <TKey> range) { switch (this.items.Count) { case 0: break; case 1: var single = this.items[0]; var singleFrom = Incrementor <TKey> .Max(single.Key.From, range.From); var singleTo = Incrementor <TKey> .Min(single.Key.To, range.To); if (singleFrom.CompareTo(singleTo) <= 0) { yield return(new KeyValuePair <Range <TKey>, TValue>(new Range <TKey>(singleFrom, singleTo), single.Value)); } break; default: var left = RangeOperations <TKey> .BinarySearch(this.Keys, range.From); if (left < 0) { left = ~left; } var right = RangeOperations <TKey> .BinarySearch(this.Keys, range.From); if (right < 0) { right = ~right - 1; } for (var i = left; i <= right; i++) { var current = this.items[i]; var from = current.Key.From; var to = current.Key.To; yield return(new KeyValuePair <Range <TKey>, TValue>( new Range <TKey>((i == left) && (@from.CompareTo(range.From) < 0) ? range.From : from, (i == right) && (to.CompareTo(range.To) > 0) ? range.To : to), current.Value)); } break; } }
public void Negate(char from1, char to1, char from2, char to2) { var range1 = Range <char> .Create(from1, to1); var range2 = Range <char> .Create(from2, to2); RangeSet <char> positive = new[] { range1, range2 }; var negative = RangeOperations <char> .Negate(positive); this.output.WriteLine(string.Join(", ", positive.Expand())); this.output.WriteLine(negative.Expand().Count().ToString()); Assert.NotEqual(positive, negative); Assert.Equal(RangeSet <char> .All, positive ^ negative); Assert.Equal(RangeSet <char> .All, positive | negative); Assert.Equal(RangeSet <char> .Empty, positive & negative); Assert.Equal(positive, positive - negative); Assert.Equal(negative, negative - positive); var negative2 = (range1 == range2) ? ~range1 : ~positive; Assert.Equal(negative, negative2); }
public static RangeSet <T> operator &(RangeSet <T> left, RangeSet <T> right) { return(RangeOperations <T> .Intersection(left, right)); }
public static RangeSet <T> operator -(Range <T> left, RangeSet <T> right) { return(RangeOperations <T> .Subtract(new RangeSet <T>(left), right)); }
public static bool operator !=(RangeSet <T> left, RangeSet <T> right) { return(!RangeOperations <T> .Equals(left, right)); }
public static RangeSet <T> operator ~(RangeSet <T> set) { return(RangeOperations <T> .Negate(set)); }
public bool Equals(RangeSet <T> other) { return(RangeOperations <T> .Equals(this, other)); }
public static RangeSet <T> operator ^(RangeSet <T> left, T right) { return(RangeOperations <T> .Difference(left, new RangeSet <T>(right))); }
public static RangeSet <T> operator ^(T left, RangeSet <T> right) { return(RangeOperations <T> .Difference(new RangeSet <T>(left), right)); }
public bool ContainsKey(TKey key) { return(RangeOperations <TKey> .BinarySearch(this.owner.Keys, key) >= 0); }
public static RangeSet <T> operator |(RangeSet <T> left, T right) { return(left.Contains(right) ? left : RangeOperations <T> .Union(left, new RangeSet <T>(right))); }
public static RangeSet <T> operator |(RangeSet <T> left, Range <T> right) { return(RangeOperations <T> .Union(left, new RangeSet <T>(right))); }
public static RangeSet <T> operator |(T left, RangeSet <T> right) { return(right.Contains(left) ? right : RangeOperations <T> .Union(new RangeSet <T>(left), right)); }
public static RangeSet <T> operator -(RangeSet <T> left, T right) { return(RangeOperations <T> .Subtract(left, new RangeSet <T>(right))); }
public static RangeSet <T> operator &(RangeSet <T> left, Range <T> right) { return(RangeOperations <T> .Slice(left, right)); }
public static RangeSet <T> operator ~(Range <T> range) { return(RangeOperations <T> .Negate(new RangeSet <T>(range))); }