2015-12-01 2 views
10

Учитывая список диапазонов дат, я хотел бы получить список смежных диапазонов дат.Получите смежные диапазоны дат

enter image description here

Я не слишком уверен в терминологии, что я искал, но я соединил скелет:

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 

namespace ContiguousTimeSpans 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<DateRange> ranges = new List<DateRange>(); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 07:00:00"), DateTime.Parse("01/12/2015 10:00:00"))); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 06:00:00"), DateTime.Parse("01/12/2015 09:00:00"))); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 05:00:00"), DateTime.Parse("01/12/2015 08:00:00"))); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 18:00:00"), DateTime.Parse("01/12/2015 21:00:00"))); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 12:00:00"), DateTime.Parse("01/12/2015 14:00:00"))); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 20:00:00"), DateTime.Parse("01/12/2015 22:00:00"))); 
      ranges.Add(new DateRange(DateTime.Parse("01/12/2015 11:00:00"), DateTime.Parse("01/12/2015 23:00:00"))); 

      List<DateRange> contiguousBlocks = GetContiguousTimespans(ranges); 
      Debug.Assert(contiguousBlocks.Count == 2); 

      Debug.Assert(contiguousBlocks[0].Start.Hour == 5); 
      Debug.Assert(contiguousBlocks[0].End.Hour == 10); 

      Debug.Assert(contiguousBlocks[1].Start.Hour == 11); 
      Debug.Assert(contiguousBlocks[1].End.Hour == 23); 

      Console.ReadKey(); 
     } 

     public static List<DateRange> GetContiguousTimespans(List<DateRange> ranges) 
     { 
      List<DateRange> result = new List<DateRange>(); 
      //??? 
      return result; 
     } 
    } 

    public class DateRange 
    { 
     public DateTime Start { get; set; } 
     public DateTime End { get; set; } 

     public DateRange(DateTime start, DateTime end) 
     { 
      Start = start; 
      End = end; 
     } 
    } 
} 

Есть ли способ вывести прилежащей диапазоны?

+0

так что ваш вопрос .. в чем проблема и или проблема с существующим кодом ..? что происходит, когда вы запускаете код ..? – MethodMan

+0

Привет MethodMan, я не знаю, как реализовать алгоритм в GetContiguousTimespans(). Попытка, которую я сделал, беспорядочна, и я не хочу загрязнять скелет – Fidel

+0

это работает ..? – MethodMan

ответ

7

Не уверен, что я понимаю, это полностью, но относительно того, что написано, и данные испытаний это должно работать:

public static List<DateRange> GetContiguousTimespans(List<DateRange> ranges) 
{ 
    List<DateRange> result = new List<DateRange>(); 
    ranges.Sort((a,b)=>a.Start.CompareTo(b.Start)); 
    DateRange cur = ranges[0]; 

    for (int i = 1; i < ranges.Count; i++) 
    { 
     if (ranges[i].Start <= cur.End) 
     { 
      if (ranges[i].End >= cur.End) 
       cur.End = ranges[i].End; 
     } 
     else 
     { 
      result.Add(cur); 
      cur = ranges[i]; 
     } 
    } 

    result.Add(cur); 

    return result; 
} 

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

+0

Примечание: вам не нужно проверять 'диапазоны [i] .Start> = cur.Start', потому что вы уже отсортировали диапазоны раньше, чем раньше. –

+0

Вы правы - эта часть выражения всегда верна) Он остается там из предыдущей версии. Но, с другой стороны, немного легче понять, что происходит с этим условием) В любом случае, спасибо! – MagisterCrazy

+0

Это очень мило Магистр, спасибо за алгоритм! – Fidel

1

Спасибо Киви. Я посмотрел на Time Period Library, и у него есть функция под названием «Time Period Combiner», которая именно то, что я искал.

enter image description here

И код, чтобы использовать его в моем случае был:

public static List<DateRange> GetContiguousTimespans(List<DateRange> ranges) 
{ 
    //convert my DateRange objects into the objects used by the Time Period Library 
    TimePeriodCollection periods = new TimePeriodCollection(); 
    ranges.ForEach(ts => periods.Add(new TimeRange(ts.Start, ts.End))); 

    //get a list of contiguous date ranges 
    TimePeriodCombiner<TimeRange> periodCombiner = new TimePeriodCombiner<TimeRange>(); 
    ITimePeriodCollection combinedPeriods = periodCombiner.CombinePeriods(periods); 

    //convert the objects back to DateRanges 
    List<DateRange> result = combinedPeriods.Select(cp => new DateRange(cp.Start, cp.End)).ToList(); 
    return result; 
} 
2

Так что, если я начну с этим входом:

List<DateRange> ranges = new List<DateRange>() 
{ 
    new DateRange(DateTime.Parse("01/12/2015 07:00:00"), DateTime.Parse("01/12/2015 10:00:00")), 
    new DateRange(DateTime.Parse("01/12/2015 06:00:00"), DateTime.Parse("01/12/2015 09:00:00")), 
    new DateRange(DateTime.Parse("01/12/2015 05:00:00"), DateTime.Parse("01/12/2015 08:00:00")), 
    new DateRange(DateTime.Parse("01/12/2015 18:00:00"), DateTime.Parse("01/12/2015 21:00:00")), 
    new DateRange(DateTime.Parse("01/12/2015 12:00:00"), DateTime.Parse("01/12/2015 14:00:00")), 
    new DateRange(DateTime.Parse("01/12/2015 20:00:00"), DateTime.Parse("01/12/2015 22:00:00")), 
    new DateRange(DateTime.Parse("01/12/2015 11:00:00"), DateTime.Parse("01/12/2015 23:00:00")), 
}; 

Тогда это работает для меня:

var ordered = ranges.OrderBy(x => x.Start).ThenBy(x => x.End).ToArray(); 

var working = 
    ordered 
     .Skip(1) 
     .Aggregate(new 
     { 
      contiguous = new List<DateRange>(), 
      current = ordered.First(), 
     }, (a, r) => 
     { 
      if (a.current.End >= r.Start) 
      { 
       return new 
       { 
        a.contiguous, 
        current = r.End > a.current.End 
         ? new DateRange(a.current.Start, r.End) 
         : a.current, 
       }; 
      } 
      else 
      { 
       a.contiguous.Add(a.current); 
       return new 
       { 
        a.contiguous, 
        current = r, 
       }; 
      } 
     }); 

var results = working.contiguous; 
results.Add(working.current); 

Конечный результат я получаю это:

results

Смежные вопросы