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

时间:2009-05-05 13:27:36

标签: c# .net linq

我有一个小问题,我想在linq中找到列表中的下一个“活动”项。然后,下一个“活动”项由startDate和EndDate定义。这是一个示例列表。

    //-- 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>();

通过在Turn上使用startDate / endDate属性找到下一个回合是否有一个很好的解决方案。我试图首先按照startdate排序列表,然后在列表中查找第一个,但是如果有更“安全”的方法可以获得它,那么就不需要列表以正确的顺序找到正确的转弯。

3 个答案:

答案 0 :(得分:1)

你可以这样做。

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

Where调用是可选的 - 其目标是减少必须订购的商品数量。

答案 1 :(得分:0)

我想你只是想:

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

这将返回包含或在给定日期today之后的第一个回合,这似乎是您正在寻找的。当然,它还假设您的turns列表已经排序。

编辑:看来我错过了一些关于你不想对列表进行排序的内容。我仍然不能完全确定选择适当的转弯所需的条件,这将使我能够改进查询。

答案 2 :(得分:0)

为什么不在今天之后获得第一个带开始日期的项目?我添加了一个explict OrderBy()调用,以确保列表已排序。如果您知道它已经排序,那么您可以将其排除在外。

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

<强>更新

我错过了你的最后一句话。是的,您可以在不明确排序列表的情况下执行此操作。您必须在列表中搜索具有今天之后的开始日期的项目,并且必须是在今天之后但在当前项目之前没有开始日期的项目。但这确实会减慢搜索速度,因为你必须查看每个项目的整个列表,使得事物为O(n²)。

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

这假设转弯不重叠。如果它们重叠,则必须使用First代替Single或添加其他约束以获得唯一结果。 最后:使用排序解决方案 - 此解决方案绝不比排序和获取第一个项目更安全。