2013-10-01 2 views
2

У меня проблема с решением C#, проблема стала слишком сложной для простого решения.Как создать список диапазонов времени на основе пересечений из двух списков временных диапазонов?

У меня есть два списка временных диапазонов плюс значение для каждого диапазона: ListA; LISTB. Между ними нет никакой связи.

Я хотел бы создать третий список (ListC) на основе ListB, где для каждой пары начала и конца в ListB, если диапазон не существует в целом в любом временном диапазоне в ListA, создайте две или несколько записей в ListC, чтобы новые записи были охвачены записями в ListA. (Извините, это трудно объяснить, не будучи слишком подробным)

Простой пример, который содержит один вид перекрытия. Между двумя списками могут быть всевозможные совпадения.

List<Tuple<int, DateTime, DateTime>> listA = new List<Tuple<int, DateTime, DateTime>>();   
listA.Add(new Tuple<int, DateTime, DateTime>(22,DateTime.Parse("09/01/2013 11:00"),DateTime.Parse("09/01/2013 12:00"))); 
listA.Add(new Tuple<int, DateTime, DateTime>(66, DateTime.Parse("09/01/2013 12:01"), DateTime.Parse("09/01/2013 14:00"))); 


List<Tuple<int, DateTime, DateTime>> listB = new List<Tuple<int, DateTime, DateTime>>(); 
listB.Add(new Tuple<int, DateTime, DateTime>(33, DateTime.Parse("09/01/2013 11:30"), DateTime.Parse("09/01/2013 13:30"))); 

//Desired List 
List<Tuple<int, DateTime, DateTime>> listC = new List<Tuple<int, DateTime, DateTime>>(); 
//listC should contain 2 tuples: first tuple contains the segment from ListB which falls in the first ListA tuple: Tuple(33, "09/01/2013 11:30","09/01/2013 12:00") 
//second tuple contains the segment which falls in second ListA tuple: Tuple(33, "09/01/2013 12:01","09/01/2013 13:30") 

ответ

1

Это моя попытка. Решение довольно просто, возможно, я неправильно понял задачу. Вы можете cosider, если нужно, используя < =,> = вместо <,> в строках, указанных в комментариях:

 List<Tuple<int, DateTime, DateTime>> listA = new List<Tuple<int, DateTime, DateTime>>(); 
     listA.Add(new Tuple<int, DateTime, DateTime>(22, DateTime.Parse("09/01/2013 11:00"), DateTime.Parse("09/01/2013 12:00"))); 
     listA.Add(new Tuple<int, DateTime, DateTime>(66, DateTime.Parse("09/01/2013 12:01"), DateTime.Parse("09/01/2013 14:00"))); 


     List<Tuple<int, DateTime, DateTime>> listB = new List<Tuple<int, DateTime, DateTime>>(); 
     listB.Add(new Tuple<int, DateTime, DateTime>(33, DateTime.Parse("09/01/2013 11:30"), DateTime.Parse("09/01/2013 13:30"))); 

     List<Tuple<int, DateTime, DateTime>> listC = new List<Tuple<int, DateTime, DateTime>>(); 

     foreach (var rangeB in listB) 
     { 
      //a range in A overlaps with a range B 
      //if any end of the range in A is inside the range in B 
      //consider using <= and/or >= in these two lines if needed 
      var overlapping = listA.Where(rangeA => rangeB.Item2 < rangeA.Item2 && rangeA.Item2 < rangeB.Item3 || 
       rangeB.Item2 < rangeA.Item3 && rangeA.Item3 < rangeB.Item3).ToList(); 

      overlapping = overlapping.Select(rangeA => 
       new Tuple<int, DateTime, DateTime> (rangeB.Item1, 
        //If a date of A is outside of B 
        //this will make it equal to the corresponding date of B 
        (rangeA.Item2 < rangeB.Item2) ? rangeB.Item2 : rangeA.Item2, 
        (rangeB.Item3 < rangeA.Item3) ? rangeB.Item3 : rangeA.Item3)).ToList(); 

      listC.AddRange(overlapping); 
     } 
0

Это поможет вам значительно, если вы использовали класс вдоль этих линий, чтобы держать ваши данные.

public class Range 
{ 
    public int Id {get; set:} 
    public DateTime Start {get; set:} 
    public DateTime End {get; set:} 
} 

Было бы проще для вас, чтобы сравнить каждое из значений в списке В с каждым из значений Start и End в список А, чтобы увидеть, если есть какие-либо перекрытия (из которых только 4 можно типы)

Type 1: B.Start < A.Start && B.End > A.End  (where B totally contains A) 
Type 2: B.Start >= A.Start && B.End <= A.End (where A totally contains B) 
Type 3: B.Start >= A.Start && B.Start <= A.End (where B overlaps to the right) 
Type 4: B.End >= A.Start && B.End <= A.End  (where B overlaps to the left) 

Псевдо код что-то вроде

Loop through all entries in List B 
{ 
    Loop through all entries in A looking for overlaps 
    { 
     If there is an overlap 
     { 
      Create a new range from the 
      appropriate Start and End values 
      from A or B as required. 

      Use the ID from B 

      Add new Range(s) as required 
     } 
    } 
} 
0

Вы можете использовать Time Period Library for .NET для расчета перекрестки:

// ---------------------------------------------------------------------- 
public void PeriodIntersection() 
{ 
    // time periods 
    ITimePeriodCollection periods = new TimePeriodCollection(); 
    periods.Add(new TimeRange(new DateTime(2013, 9, 1, 11, 0, 0), new DateTime(2013, 9, 1, 12, 0, 0))); 
    periods.Add(new TimeRange(new DateTime(2013, 9, 1, 12, 1, 0), new DateTime(2013, 9, 1, 14, 0, 0))); 

    // search range 
    TimeRange searchRange = new TimeRange(new DateTime(2013, 9, 1, 11, 30, 0), new DateTime(2013, 9, 1, 13, 30, 0)); 

    // intersections 
    foreach (TimeRange period in periods) 
    { 
    if (period.IntersectsWith(searchRange)) 
    { 
     Console.WriteLine("Intersection: " + period.GetIntersection(searchRange)); 
    } 
    } 
    // > Intersection: 01.09.2013 11.30:00 - 12:00:00 | 0.00:30 
    // > Intersection: 01.09.2013 12.01:00 - 13:30:00 | 0.01:29 
} // PeriodIntersection 
Смежные вопросы