Mark Johnson February 2016

Removing Overlapping Dates in LINQ

I have a really ghetto implementation of this, but I imagine there is some clean way to do this with Linq. I have a list of objects with a start and stop date.

class Thing
{
  int ID;
  ...
  DateTime? StartDate;
  DateTime EndDate;
}

In some cases there is no start date, its null. What I want the algorithm to do is remove items from the list until there is no overlapping of dates; I'm just using years to illustrate the concept:

List<Thing> x = new List<Thing>()
{
  {1, 2012, 2014}
  {2, 2013, 2015}
  {3, 2014, 2016}
  {4, <null>, 2015}
  {5, 2016, 2017}
}

Running this list through the algo should yield:

var y = Do(x);

y =
{
  {1, 2012, 2014}
  {2, <null>, 2015}
  {3, 2016, 2017}
}

There is the possibilities for cycles where, where there are different optimal solutions. My data doesn't have these edge cases.

Answers


tparnell February 2016

If your class Thing implements IEquatable<Thing> and you properly fill out the Equals, and GetHashCode methods you can then just do

var results = x.Distinct();


Enigmativity February 2016

I think this should work for you:

List<Thing> x = new List<Thing>()
{
    new Thing () { ID = 1, StartDate = new DateTime(2012, 1, 1), EndDate  = new DateTime(2014, 1, 1) },
    new Thing () { ID = 2, StartDate = new DateTime(2013, 1, 1), EndDate  = new DateTime(2015, 1, 1) },
    new Thing () { ID = 3, StartDate = new DateTime(2014, 1, 1), EndDate  = new DateTime(2016, 1, 1) },
    new Thing () { ID = 4, StartDate = null, EndDate  = new DateTime(2015, 1, 1) },
    new Thing () { ID = 5, StartDate = new DateTime(2016, 1, 1), EndDate  = new DateTime(2017, 1, 1) },
};

Func<Thing, Thing, bool> overlaps =
    (t0, t1) =>
        (t0.StartDate.HasValue ? t0.StartDate.Value <= t1.EndDate : false)
            && (t1.StartDate.HasValue ? t0.EndDate >= t1.StartDate : false);

var y = x.Skip(1).Aggregate(x.Take(1).ToList(), (a, b) =>
{
    if (a.All(c => !overlaps(b, c)))
    {
        a.Add(b);
    }
    return a;
});

This gives me:

y

Post Status

Asked in February 2016
Viewed 1,133 times
Voted 8
Answered 2 times

Search




Leave an answer