获取最大时间间隔的linq查询

时间:2011-05-23 19:09:09

标签: c# linq c#-4.0 .net-4.0

我一直在研究一些基本的linq,但我不确定如何实现这个。

考虑一个像这样的简单对象

public class Movement
{
    int areaId;
    DateTime startTime;
    DateTime endTime;
}

这表示某个项目的移动。 startTime是它使用areaId进入区域的时间。 endTime是它离开该区域的时间。 我没有特定顺序的一个项目的列表。任何areaId都可以有许多不同的运动,并且没有时间重叠。

List<Movement> items = getSomeMovements();

给我一​​个时间间隔,由低时间和高时间定义。低时间不到很长时间。

DateTime lowTime;
DateTime highTime;

我希望在此时间间隔内获取项目花费最多时间的areaId。 我想按区域分组,找到每个区域的总时间,并选择最大的总数。不知道如何使用Linq这样做。我感谢任何帮助。

5 个答案:

答案 0 :(得分:1)

如果我理解你的问题,

这样的事情应该这样做:

var areaTime = from mov in items
               where mov.startTime >= lowTime && mov.endTime <= highTime
               group mov by mov.areaId into grp
               select new
               {
                   AreaID = grp.Key,
                   TimeSpent = grp.Sum(m => (m.endTime - m.startTime).TotalSeconds),
               };

var areaSpentMostTimeIn = areaTime
    .OrderByDescending(at => at.TimeSpent)
    .FirstOrDefault();

答案 1 :(得分:1)

这可以用纯LINQ完成,但更整洁,首先声明两个函数:

TimeSpan Intersection(DateTime start, DateTime end, Movement movement)
{
    DateTime t1 = start > movement.StartTime ? start : movement.StartTime;
    DateTime t2 = end < movement.EndTime ? end  : movemnt.EndTime;
    return t1 < t2 ? t2 - t1 : TimeSpan.Empty;
}

然后使用:items.OrderByDescending(m => Intersection(lowTime, hightTime, m).FirstOrDefault()

如果将交点添加到班级移动

,这将更加清晰

答案 2 :(得分:0)

你的意思是:

List<Movement> items = getSomeMovements();
Movement result = items.OrderByDescending(m => m.endTime - m.startTime).FirstOrDefault();

答案 3 :(得分:0)

使用Aggregate可以简单得多。完整的测试数据示例:

var now = DateTime.Now;
var movements = new []
{
    new Movement { areaId = 1, startTime = now.AddDays(-10), endTime = now.AddDays(-9) },
    new Movement { areaId = 2, startTime = now.AddDays(-8), endTime = now.AddDays(-7) },
    new Movement { areaId = 3, startTime = now.AddDays(-5), endTime = now.AddDays(-2) },
    new Movement { areaId = 4, startTime = now.AddDays(-2), endTime = now.AddDays(0) }
};

var longest = movements.Aggregate((m1, m2) =>
    m1.endTime.Subtract(m1.startTime) > m2.endTime.Subtract(m2.startTime) ? m1 : m2
);

答案 4 :(得分:0)

使用Alireza的交叉功能,但聚合而不是订购会更有效率。