How to get the next active item in a list with LINQ

I have a little problem where I want to find the next "active" item in a list with linq. Then the next "active" element is defined by startDate and EndDate. Here is a list of examples.

    //-- Create Lists of turns    
    IList<Turn> turns= new List<Turn>(){ 
                new Turn(){Name = "Turn 1", StartDate = DateTime.Parse("2009-05-01"), EndDate = DateTime.Parse("2009-05-01") }
         ,      new Turn(){Name = "Turn 2", StartDate = DateTime.Parse("2009-06-01"), EndDate = DateTime.Parse("2009-06-01") }
         ,      new Turn(){Name = "Turn 3", StartDate = DateTime.Parse("2009-07-01"), EndDate = DateTime.Parse("2009-07-02") }
         ,      new Turn(){Name = "Turn 4", StartDate = DateTime.Parse("2009-08-01"), EndDate = DateTime.Parse("2009-08-03") }
    }

//-- Get the next Turn by DateTime.
DateTime toDay = DateTime.Parse("2009-06-02");

//-- Should return the "Turn 3" item...
Turn turn = (from item in turns
            where .....
            select turn).FirstOrDefault<Turn>();

      

Is there a good solution to find the next turn using the startDate / endDate properties on Turn. I tried to first order the list by startdate and find First in the list, but I realized there was a "safer" way to get it so that it doesn't need the list in the correct order to find the correct Turn.

+1


source to share


3 answers


Why don't you just get the first item with a start date after today? I added an explict call OrderBy()

to make sure the list is sorted. If you know it's sorted, you can leave that, of course.

turns.OrderBy(t => t.StartDate).FirstOrDefault(t => t.StartDate > today);

      

UPDATE



I missed the last lines. Yes, you can do this without explicitly sorting the list. You should search the list for an element with a start date after today, and ther should not be an element with a start date after today, but before the current position. But this will really slow down the search, because you have to loop through the entire list for each element doing the O (n²) thing.

turns.Single(t => 
    t.StartDate > today &&
    turns.All(u => u.StartDate <= today || u.StartDate > t.StartDate))

      

This assumes the turns do not overlap. If they overlap, you must use First

instead Single

or add additional constraints to get a unique result. Finally, use a sorting solution - this solution is by no means safer than sorting and getting the first item.

0


source


You can do it.

Turn turn = turns
  .Where(t => t.StartDate >= toDay)
  .OrderBy(t => t.StartDate)
  .FirstOrDefault();

      



The Where query is optional - its purpose is to reduce the number of items to order.

+1


source


I guess you just want:

var turn = turns.SkipWhile(t => t.EndDate < today).FirstOrDefault();

      

This will return the first move that contains or after the specified date today

, which is what you seem to be looking for. It also assumes that your list is turns

already sorted, of course.

Edit: Looks like I missed the bit about not wanting to sort the list. I'm still not entirely sure if you need to choose the appropriate rotation that will allow me to improve the query.

0


source







All Articles