Как проверить наличие пробелов между свойствами даты в списке объектов?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Как проверить наличие пробелов между свойствами даты в списке объектов?

Сообщение Anonymous »

Мой наставник и я сейчас переписываем функциональность нашего проекта. Среди всего прочего, что нам предстоит сделать, есть решающая часть, которая включает в себя проверку наличия пробелов между историями. Все, что мы делаем дальше, зависит от проверки пробелов. Вот наш урок истории:

Код: Выделить всё

public class History : IEntityBase, IEntityDates
{
[Key]
public long Id { get; set; }

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

/* =================== Not Mapped properties =================== */

[NotMapped]
public bool HasGap { get; set; }

[NotMapped]
public bool IsGapSixMonthsOrMore { get; set; }
}
По сути, метод принимает список и проверяет, есть ли пробел.
Вопрос: Что такое пробел?

A: Разрыв определяется как минимальное количество дней между двумя датами (не включая), чтобы свойство HasGap было истинным.
Здесь также приведена некоторая информация о типах истории, которые мы можем ожидать, и возможные результаты:
  • История может иметь нулевую EndDate (A), и это означает, что история все еще продолжается, и каждая история, чья StartDate после A.StartDate не будет пробела.
  • В отсортированном списке истории могут перекрываться. Это означает, что одна история может закончиться, в то время как другая история началась за 2 месяца до окончания.
  • В истории будет пробел, если histories.StartDate предшествует histories[i-1]. EndDate не менее 7 (пропускных) дней.
  • histories.IsGapSixMonthsOrMore — это истинная история.StartDate предшествует истории[i-1].EndDate не менее чем на 6 месяцев. .
  • StartDate также может иметь значение null, но никогда не бывает так, потому что мы выполняем эту проверку в другой функции при получении всех данных.

Если придумаю что-нибудь еще, я напишу.
Мы написали два разных метода расчета, но оба они зависят от списка историй, которые нужно отсортировать. Итак, нам интересно, есть ли способ выполнить эту проверку без зависимости от сортируемого списка?
Его решение выполняет вычисления вдвое быстрее, чем мое.
Вот это его:

Код: Выделить всё

public static void CalculateGaps(this List dateRanges, int? gapThreshold)
{
if (dateRanges == null || dateRanges.Count < 2 || gapThreshold is null)
return;

// Sort the ranges by Start date
var sortedRanges = dateRanges.OrderBy(r => r.StartDate)
.ThenBy(r => r.EndDate)
.ToList();

// Initialize the first range with no gap (as it's the first in the list)
sortedRanges[0].HasGap = false;
sortedRanges[0].IsGapSixMonthsOrMore = false;

// Keep track of the latest 'end' date encountered
DateTime currentMaxEnd = sortedRanges[0].EndDate?.Date ?? DateTime.MaxValue;

for (int i = 1; i < sortedRanges.Count; i++)
{
// If there's a gap between the current maximum end and the next range's start
if (currentMaxEnd < sortedRanges[i].StartDate?.Date.AddDays(-gapThreshold.Value))
{
sortedRanges[i].HasGap = true; // Gap found

// Check if the gap is more than 6 months
sortedRanges[i].IsGapSixMonthsOrMore = sortedRanges[i].StartDate?.Date.AddMonths(-6) >= currentMaxEnd;
}
else
{
sortedRanges[i].HasGap = false;
sortedRanges[i].IsGapSixMonthsOrMore = false;
}

// Update the max end to be the later of the current max end or this range's end
var nextEnd = sortedRanges[i].EndDate?.Date ?? DateTime.MaxValue;
currentMaxEnd = currentMaxEnd > nextEnd ? currentMaxEnd : nextEnd;
}
}
Вот мой, я шел по тому же пути, что и он, но смог пройти несколько тестовых случаев с несколькими перекрывающимися историями. Поэтому я реализовал своего рода очередь, чтобы помочь с перекрытием:

Код: Выделить всё

public static void CalculateGapsV2(this List histories, int? gapThreshold)
{
if (histories.Count == 0)
return;

histories = histories.OrderBy(h => h.StartDate).ToList();

var queue = new Queue();

histories[0].HasGap = false; // First entry has no previous history to compare with
histories[0].IsGapSixMonthsOrMore = false; // First entry has no previous history to compare with

queue.Enqueue(histories[0].EndDate?.Date);

for (int i = 1; i < histories.Count; i++)
{
var previousEndDate = histories[i - 1].EndDate?.Date;
var currentStartDate = histories[i].StartDate?.Date;

while (queue.Count > 0)
{
if (queue.Peek() is null) //ongoing history
{
histories[i].HasGap = false;
histories[i].IsGapSixMonthsOrMore = false;
break;
}
else if (queue.Peek() > currentStartDate)
{
histories[i].HasGap = false;
histories[i].IsGapSixMonthsOrMore = false;
queue.Enqueue(histories[i].EndDate?.Date);
break;
}
else
{
queue.Dequeue();
}
}

if (queue.Count == 0)
{
if (currentStartDate is null)
{
histories[i].HasGap = false;
histories[i].IsGapSixMonthsOrMore = false;
}
else
{
var gapDays = (currentStartDate.Value - previousEndDate.Value).TotalDays;

//A gap is defined as total days between two employments
//So if a gapThreshold = 1
//Has gap would be false if hist[0].EndDate = 2024-10-1 and hist[1].StartDate = 2024-10-2
//But has gap would be true if hist[0].EndDate = 2024-10-1 and hist[1].StartDate = 2024-10-3
//Since we only have one full day between, and that is 2024-10-2
histories[i].HasGap = gapDays > gapThreshold;

// The six month gap is defined as six months or more
// hist[0].EndDate = 2024-1-15  and hist[1].StartDate = 2024-7-15
// This would make the bool true
// If startDate was 2024-07-14 -> IsGapSixMonthsOrMore would be false
histories[i].IsGapSixMonthsOrMore = currentStartDate.Value.AddMonths(-6) >= previousEndDate.Value;

queue.Enqueue(histories[i].EndDate?.Date);
}
}
}
}
Сводка и вопрос
Оба метода прошли все наши тестовые примеры.
Просто чтобы подтвердить вопрос. Есть ли более эффективный способ сделать это, не зависящий от списка историй, которые нужно отсортировать? Если нет, есть ли возможности для улучшения метода CalculateGaps()?

Подробнее здесь: https://stackoverflow.com/questions/790 ... of-objects
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как проверить наличие букв и пробелов
    Гость » » в форуме C++
    0 Ответы
    38 Просмотры
    Последнее сообщение Гость
  • Как предотвратить наличие нескольких пробелов между словами в EditText?
    Anonymous » » в форуме Android
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous
  • Как проверить наличие строки в постоянном списке строк
    Anonymous » » в форуме C#
    0 Ответы
    2 Просмотры
    Последнее сообщение Anonymous
  • Как проанализировать pom.xml Maven на наличие ошибок (линтер pom на наличие избыточных или игнорируемых свойств?)
    Anonymous » » в форуме JAVA
    0 Ответы
    138 Просмотры
    Последнее сообщение Anonymous
  • Как установить значение даты по умолчанию в качестве текущей даты в текстовом поле выбора даты?
    Anonymous » » в форуме Jquery
    0 Ответы
    323 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»