如何筛选List中同Url且FinishedAt时间差超1小时的DomainTimeErrors对象
解决方案
要搞定这个需求,咱们可以借助LINQ的分组和筛选能力,分步骤处理你的列表:
核心思路
- 按Url分组:把所有Url相同的对象归为一组,这样就能针对每个Url单独分析时间差。
- 校验时间间隔:对每个分组,先过滤掉
FinishedAt为null的无效数据(如果有的话),然后计算该分组内最早和最晚FinishedAt的时间差,判断是否超过1小时。 - 提取目标数据:筛选出符合时间差条件的分组,你可以选择取出该分组的所有对象,或者像你示例中那样只取其中一个。
代码实现
场景1:获取所有符合条件的对象
如果你需要拿到所有属于符合条件的Url下的对象,可以用这段代码:
// 定义1小时的时间阈值 var oneHourThreshold = TimeSpan.FromHours(1); var matchingObjects = list // 按Url对对象分组 .GroupBy(item => item.Url) // 筛选出时间差超1小时的分组 .Where(group => // 确保分组里至少有2个有效的FinishedAt值(否则没法计算时间差) group.Count(item => item.FinishedAt.HasValue) >= 2 && // 计算最早和最晚时间的差值 group.Max(item => item.FinishedAt.Value) - group.Min(item => item.FinishedAt.Value) > oneHourThreshold ) // 把符合条件的分组里的所有对象合并成一个列表 .SelectMany(group => group) .ToList();
场景2:每个符合条件的Url只取一个对象
如果像你的示例那样,只需要每个符合条件的Url返回一个对象(比如so.com/id=1的任意一个),可以把最后一步改成这样:
var matchingObjects = list .GroupBy(item => item.Url) .Where(group => group.Count(item => item.FinishedAt.HasValue) >= 2 && group.Max(item => item.FinishedAt.Value) - group.Min(item => item.FinishedAt.Value) > oneHourThreshold ) // 取每个分组的第一个对象(也可以按需取Last()或者其他) .Select(group => group.First()) .ToList();
针对你的示例数据的结果
用你提供的测试列表跑代码的话:
Url = "so.com/id=1"的分组:最早时间是2017-12-01 12:00,最晚是2017-12-01 14:00,时间差2小时,超过阈值,会被选中。Url = "so.com/id=2"的分组:最早时间2017-12-01 12:00,最晚2017-12-01 12:56,差56分钟,没到1小时,会被排除。
注意点
- 代码里过滤了
FinishedAt为null的对象,如果你业务中需要处理null的情况(比如把null视为最早/最晚时间),可以调整Where里的判断逻辑。 - 你的示例代码里直接给
FinishedAt赋值字符串是错误的,实际开发中要使用DateTime.Parse("2017-12-01 12:00")或者更安全的DateTime.TryParse来转换。
内容的提问来源于stack exchange,提问作者Tomasz Kowalczyk
相关产品推荐
相关产品推荐

