Найдите отношения периодов в списке с помощью LINQ - PullRequest
0 голосов
/ 18 июня 2020

У меня есть класс, который содержит информацию о дате периода, начала и конца:

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}

, тогда у меня есть список объектов A, где я объявил несколько периодов:

List<A> listOfA = new List<A>()
{
     new A {Id=1,Name="1", Start = new DateTime (2020,1,1), End = new DateTime(2020,1,20) },
     new A {Id=2,Name="2", Start = new DateTime (2020,1,21), End = new DateTime(2020,2,20) },
     new A {Id=3,Name="3", Start = new DateTime (2020,5,11), End = new DateTime(2020,5,14) },
     new A {Id=4,Name="4", Start = new DateTime (2020,5,15), End = new DateTime(2020,5,20) }
};

Я хочу найти связь (перекрывающуюся, содержащую et c.) Между заданными периодами и периодами в списке:

var wrong = new A { Id = 5, Name = "5", Start = new DateTime(2020, 1, 3), End = new DateTime(2020, 4, 20) };
var ok = new A { Id = 6, Name = "6", Start = new DateTime(2020, 4, 3), End = new DateTime(2020, 4, 14) };

В приведенном выше примере неправильный объект имеет дату начала внутри одного из объектов в списке и хорошо к объекту отношения не имеют. Как найти это отношение с помощью LINQ?

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Это квадратичная c временная сложность и полностью непроверена, однако выглядит хорошо, и это то, что имеет значение

var results = list.Where(x => 
                    list.Any(y =>
                         x != y && 
                         (x.Start >= y.Start && x.Start <= y.End ||
                         x.End <= y.End && x.End >= y.Start)))
                  .ToList();

Или

Учитывая

public class A
{
     public int Id { get; set; }
     public string Name { get; set; }
     public DateTime Start { get; set; }
     public DateTime End { get; set; }

     public bool Intersect(A a)
        => this != a && (Start >= a.Start && a.Start <= a.End || End <= a.End && End >= a.Start);
}

Использование

var wrong = list.Where(x => list.Any(x.Intersect)).ToList();
var good = list.Except(wrong).ToList();
0 голосов
/ 18 июня 2020

Вы можете попробовать:

var wrong2 = listOfA.Any(i => wrong.End > i.Start && wrong.Start < i.End);
var ok2 = listOfA.Any(i => ok.End > i.Start && ok.Start < i.End);

"неправильно2" будет истинным (перекрытие). «ok2» будет ложным (без перекрытия).

Изменить: возможно, вам стоит подумать о создании объекта «Period», который будет иметь «StartDate» и «EndDate» и метод «IsOverlapping». Результат будет таким же, но более читабельным :-) (См .: ValueObject ).

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