Может ли кто-нибудь упростить этот алгоритм для меня? - PullRequest
9 голосов
/ 20 апреля 2010

По сути, я просто хочу проверить, перекрывается ли один период времени с другим. Нулевая дата окончания означает до бесконечности. Может ли кто-нибудь сократить это для меня, поскольку его довольно трудно читать время от времени. Приветствия

    public class TimePeriod
    {
        public DateTime StartDate { get; set; }
        public DateTime? EndDate { get; set; }

        public bool Overlaps(TimePeriod other)
        {
            // Means it overlaps
            if (other.StartDate == this.StartDate
                || other.EndDate == this.StartDate
                || other.StartDate == this.EndDate
                || other.EndDate == this.EndDate)
                return true;

            if(this.StartDate > other.StartDate)
            {
                // Negative
                if (this.EndDate.HasValue)
                {
                    if (this.EndDate.Value < other.StartDate)
                        return true;
                    if (other.EndDate.HasValue && this.EndDate.Value < other.EndDate.Value)
                        return true;
                }

                // Negative
                if (other.EndDate.HasValue)
                {
                    if (other.EndDate.Value > this.StartDate)
                        return true;
                    if (this.EndDate.HasValue && other.EndDate.Value > this.EndDate.Value)
                        return true;
                }
                else
                    return true;
            }
            else if(this.StartDate < other.StartDate)
            {
                // Negative
                if (this.EndDate.HasValue)
                {
                    if (this.EndDate.Value > other.StartDate)
                        return true;
                    if (other.EndDate.HasValue && this.EndDate.Value > other.EndDate.Value)
                        return true;
                }
                else
                    return true;

                // Negative
                if (other.EndDate.HasValue)
                {
                    if (other.EndDate.Value < this.StartDate)
                        return true;
                    if (this.EndDate.HasValue && other.EndDate.Value < this.EndDate.Value)
                        return true;
                }
            }

            return false;
        }
    }

Ответы [ 4 ]

15 голосов
/ 20 апреля 2010
public bool Overlaps(TimePeriod other)
{
    return (other.StartDate >= StartDate && 
               (EndDate == null || other.StartDate <= EndDate.Value)) ||
           (StartDate >= other.StartDate &&
               (other.EndDate == null || StartDate <= other.EndDate.Value))
}
11 голосов
/ 20 апреля 2010

Как насчет этого:

public bool Overlaps(TimePeriod other)
{
    bool isOtherEarlier = this.StartDate > other.StartDate;
    TimePeriod earlier = isOtherEarlier  ? other : this;
    TimePeriod later = isOtherEarlier ? this : other;
    return !earlier.EndDate.HasValue || earlier.EndDate > later.StartDate;
}
3 голосов
/ 20 апреля 2010

Проверьте это: DateTimeOverlaps

В целом, если все переменные имеют временные значения, допускающие значение NULL, то

   return (StartA.HasValue? StartA.Value:DateTime.Minimum) <= 
             (EndB.HasValue? EndB.Value:DateTime.Maximum)  && 
          (EndA.HasValue? EndA.Value:DateTime.Maximum) >= 
              (StartB.HasValue? StartB.Value:DateTime.Minimum);

Концепция (как объяснено в ссылке) очень проста и представляет собой просто и кратко , изложенные выше.

Если начало предшествует концу других, а конец - после другого начала, у вас есть совпадение. Это говорит обо всем и обо всем, что необходимо, в одном простом предложении с двумя предложениями, и любой код, который вы пишете, должен кратко соответствовать этой простой концепции, не запутывая ее. Добавление дополнительной ненужной сложности не добавляет понимания, оно только добавляет длины.

Сбой Случай 1: TopStart ПОСЛЕ другого завершения - Сбой

       |----------|
|--|

Сбой Случай 2: TopEnd ПОСЛЕ другого запуска - Сбой

   |-----------|
                   |------|

Во всех других случаях начало предшествует другому концу, а конец - после другого начала.

кейс A

    |----------|  
|-----|

корпус B

    | ---------|
|-------------------|

кейс C

|-----------|
   |------|

кейс D

   |-----------|
       |-------------|
2 голосов
/ 20 апреля 2010

Каждый раз, когда вы имеете дело с чистой булевой логикой, вы можете использовать свой алгоритм в одном выражении. Но не думайте, что только потому, что вы можете, вы должны. Если производительность не является жизненно важной, всегда используйте читаемый код вместо компактного. (Не та компактность == производительность, обязательно)

Это легко прочитать, потому что оно полностью состоит из одиночных выражений AND, и очевидно, что все они определяют не перекрытие:

public bool Overlaps(TimePeriod other)
{
    if (other.EndDate.HasValue && other.EndDate < StartDate)
        return false;

    if (EndDate.HasValue && EndDate < other.StartDate)
        return false;

    if (!EndDate.HasValue && other.EndDate < StartDate)
        return false;

    if (!other.EndDate.HasValue && EndDate < other.StartDate)
        return false;

    return true;
}

Не то чтобы другие ответы были плохими (мне нравятся ответы Адама; его форматирование явно предназначено для удобства чтения). Я просто говорю это, потому что ясно, что вы новичок, и я думаю, что это один урок, который недостаточно учтен (я виноват). Кто-то (я думаю, что Мартин Фаулер) однажды сказал что-то вроде: «Любой дурак может написать код, понятный компьютеру, но хороший программист может написать код, понятный человеку».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...