简体   繁体   English

如何使用LINQ获取列表中的下一个活动项目

[英]How to get next active item in a list with LINQ

I have a small problem where I want to find the next "active" item in a list with linq. 我有一个小问题,我想在linq列表中找到下一个“活动”项目。 Then next "active" item is defined by a startDate and EndDate. 然后,下一个“活动”项由startDate和EndDate定义。 Here is an example list. 这是一个示例列表。

    //-- 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 by using startDate/endDate properties on Turn. 通过在Turn上使用startDate / endDate属性,找到下一个转弯的好方法吗? I have tryed to first order the list by startdate and the find First one in the list, but I wounder if there is a more "safe" way to get it that dosen't need the list in correct order to find the correct Turn. 我试图先按startdate排序,然后再找到列表中的第一个。但是,如果有一种更“安全”的方式来获取它,并且不需要以正确的顺序来找到正确的转弯,我就很伤心。

You could do this. 你可以做到这一点。

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

The Where call is optional - its goal is to reduce the amount of items that have to be ordered. Where调用是可选的-其目标是减少必须订购的物品数量。

I think you just want: 我想您只想要:

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

This would return the first turn either containing or after the given date today , which what you seem to be looking for. 这将返回包含或在today给定日期之后的第一个转弯,这似乎是您想要的。 It also assumes that your turns list is already sorted, of course. 当然,还假定您的turns列表已经排序。

Edit: It appears I missed the bit about you not wanting to sort the list. 编辑:似乎我想念您不想对列表进行排序的地方。 I'm still not completely sure on the conditions you require to select the appropiate turn, which would enable me to improve the query. 我仍然不能完全确定您选择合适转弯所需的条件,这将使我能够改善查询条件。

Why don't you just get the first item with a start date after today? 为什么您不从今天开始就获得第一项的开始日期呢? I added an explict OrderBy() call just to be sure that the list is sorted. 我添加了一个明确的OrderBy()调用只是为了确保列表已排序。 If you know that it is sorted, you can leave that out, of course. 如果您知道它已排序,则可以将其省略。

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

UPDATE 更新

I missed your last lines. 我错过了你的最后几句。 Yes, you can do it without sorting the list explicitly. 是的,您可以执行此操作而无需显式排序列表。 You have to search the list for the item with a start date after today and ther must be no item with a start date after today but before that of the current item. 您必须在列表中搜索起始日期在今天之后的项目,并且该项目不能是起始日期在今天之后但当前项目之前的项目。 But this will really slow down the search because you have to look at the whole list for every item making the thing O(n²). 但这确实会减慢搜索速度,因为您必须查看构成O(n²)的每个项目的整个列表。

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

This assumes that the turns are non-overlapping. 这假定转弯不重叠。 If they overlapp, you must use First instead of Single or add additional constraints to get a unique result. 如果它们重叠,则必须使用“ First而不是“ Single或添加其他约束以获得唯一的结果。 And finally: use the the sorting solution - this solution is by no means safer than sorting and getting the first item. 最后:使用排序解决方案-这种解决方案绝对比排序和获取第一项更为安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM