Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining consecutive dates in IList<DateTime> into ranges

Tags:

c#

linq

  1. I have a series of objects with from and to dates.
  2. Using something like:

    IList<DateTime> dates =
        this.DateRanges
            .SelectMany(r => new [] { r.From, r.To })
            .Distinct()
            .OrderBy(d => d)
            .ToList();
    

    I can get all dates without any of them being duplicated. Ranges may fully overlap, partially overlap (upper or lower overlapping), touch or they may not overlap at all.

  3. Now I need to convert this list to a different one so that each consecutive date pair forms a new generated DateTime instance right in the middle of pair

    D1      D2      D3              D4  D5
        G1      G2          G3        G4
    

    Where Dn are my distinct dates from the list and Gm dates are ones I'd like to generate in the middle of them.

Question

How do I convert an ordered list of individual dates to pairs so that I get pairs as shown in the following example? I would like to form these using LINQ instead of for loop which can accomplish the same thing. Using LINQ may result in and more efficient code due to delayed expression tree execution.

Additional explanation using a real-world example

Suppose this is my example of such ranges:

D1             D2     D3     D4   D5     D6          D11    D12
|--------------|      |------|    |------|           |------|
       D7                         D8
       |--------------------------|
D9                                              D10
|-----------------------------------------------|

First step of getting distinct dates would result in these dates:

D1     D7      D2     D3     D4   D5     D6     D10  D11    D12

D9 and D8 would fall off because they're duplicates.

Next step is to form pairs (I don't know how to do this using LINQ):

D1-D7, D7-D2, D2-D3, D3-D4, D4-D5, D5-D6, D6-D10, (D10-D11), D11-D12

Last step has to calculate a date for each pair using:

Dnew = Dfrom + (Dto - Dfrom)/2

Empty ranges issue

Range D10-D11 should preferably be omitted. But if omitting it results in over-complicates code it can be kept and excluded with a separate check afterwards. But if it can be excluded initially then that's what should be done. So if you also provide information of how to form pairs that exclude empty ranges, you're welcome to add that info as well.

like image 515
Robert Koritnik Avatar asked Oct 03 '11 12:10

Robert Koritnik


1 Answers

You can use Zip():

var middleDates = dates.Zip(dates.Skip(1), 
                            (a, b) => (a.AddTicks((b - a).Ticks / 2)))
                       .ToList();
like image 189
BrokenGlass Avatar answered Oct 26 '22 13:10

BrokenGlass