С#:Пересечение диапазона, когда конечные точки равны нулю (бесконечность)
-
19-09-2019 - |
Вопрос
Хорошо, у меня есть эти методы пересечения для работы с диапазонами, и они работают хорошо, пока конечные точки диапазона не равны нулю:
public static bool Intersects<T>(this Range<T> first, Range<T> second, IComparer<T> comparer)
{
return comparer.Compare(first.Start, second.End) <= 0
&& comparer.Compare(first.End, second.Start) >= 0;
}
public static Range<T> GetIntersectionWith<T>(this Range<T> first, Range<T> second,
IComparer<T> comparer)
{
// Return null, if any range is null or if they don't intersect at all
if (first == null || second == null || !Intersects(first, second, comparer))
return null;
var start = comparer.Compare(first.Start, second.Start) < 0
? second.Start
: first.Start;
var end = comparer.Compare(first.End, second.End) > 0
? second.End
: first.End;
return Range.Create(start, end);
}
Моя проблема сейчас в том, что я хотел бы, чтобы они поддерживали именно это, нулевые конечные точки.Нулевая конечная точка будет означать, что диапазон стремится к бесконечности в этом направлении.Два теста, которые я хотел бы пройти, но не могу, например:
[Test]
public void Intersects_Intersecting_OneEndsWithNull()
{
var a = Range.Create("a", "k");
var b = Range.Create("c", null);
Assert.That(a.Intersects(b), Is.True);
Assert.That(b.Intersects(a), Is.True);
}
[Test]
public void GetIntersectionWith_Intersecting_OneStartingAndOneEndingWithNull()
{
var a = Range.Create(null, "k");
var b = Range.Create("f", null);
var expected = Range.Create("f", "k");
Assert.That(a.GetIntersectionWith(b), Is.EqualTo(expected));
Assert.That(b.GetIntersectionWith(a), Is.EqualTo(expected));
}
Причина, по которой это не работает сразу, заключается в том, что null считается меньшим, чем все.Но здесь ноль иногда следует считать больший чем все.
Есть идеи, как это можно решить в хорошем смысле?
Я думаю, мне придется либо проверить null
сначала и сделать что-то особенное или сделать что-то вроде IComparer<T>
обертка...но я не могу понять, какие и как они должны будут работать.Следует помнить, что ему также может быть задан любой тип компаратора, поэтому технически диапазоны могут быть в противоположном направлении, если данный компаратор, конечно, учитывает это (в реальном коде я выдаю исключение, если начинается после окончания по данным компаратора).В любом случае, я здесь немного заблудился :P
Решение
Думаю, нужно учитывать нули при сравнении.
Разве это не поможет?
public static bool Intersects<T>(this Range<T> first, Range<T> second, IComparer<T> comparer)
{
return (ReferenceEquals(first.Start, null) || ReferenceEquals(second.End, null) || comparer.Compare(first.Start, second.End) <= 0)
&& (ReferenceEquals(first.End, null) || ReferenceEquals(second.Start, null) || comparer.Compare(first.End, second.Start) >= 0);
}
Хорошо, для второй части.установите для начала и конца значение null и установите значения начала/конца только в том случае, если оба значения не равны нулю.
public static Range<T> GetIntersectionWith<T>(this Range<T> first, Range<T> second, IComparer<T> comparer)
{
// Return null, if any range is null or if they don't intersect at all
if (first == null || second == null || !Intersects(first, second, comparer))
return null;
T start;
if (ReferenceEquals(first.Start, null))
start = second.Start;
else if (ReferenceEquals(second.Start, null))
start = first.Start;
else
start = comparer.Compare(first.Start, second.Start) < 0
? second.Start
: first.Start;
T end;
if (ReferenceEquals(first.End, null))
end = second.End;
else if (ReferenceEquals(second.End, null))
end = first.End;
else
end = comparer.Compare(first.End, second.End) > 0
? second.End
: first.End;
return Range.Create(start, end);
}