C #: пересечение диапазона, когда конечные точки равны нулю (бесконечность) - PullRequest
1 голос
/ 13 ноября 2009

Хорошо, у меня есть эти методы пересечения для работы с диапазонами, и они работают хорошо, пока конечные точки диапазона не равны нулю:

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 больше , чем все.

Есть идеи, как это можно решить хорошим способом?

Я думаю, что сначала мне нужно будет либо проверить null и сделать что-то особенное, либо создать какую-то оболочку IComparer<T> ... но я не могу понять, какие или как они должны это сделать Работа. Необходимо помнить, что ему может быть предоставлен также любой вид компаратора, так что технически диапазоны могут быть в противоположном направлении, если конечно данный компаратор учитывает это (в реальном коде я выкидываю исключение, если начинается после окончания в соответствии с данным компаратором). В любом случае, я немного растерялся: P

1 Ответ

1 голос
/ 13 ноября 2009

Я думаю, вам нужно учитывать нули в сравнении.

Разве это не поможет?

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);
        }

ОК, для второй части. установите начало и конец равными нулю, и установите начальные / конечные значения, только если оба значения не равны нулю.

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);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...