如何在LINQ中分组后取Top N并将剩余项合并为‘Rest’组?
LINQ分组求和后取Top N并合并剩余项为Rest组
我写了一个LINQ查询,按通话分组并对时长求和,功能正常但输出结果太多。想在分组后获取最多10条Top结果,同时把剩余项合并为‘Rest’组,用LINQ能实现吗?
当前查询示例:
IEnumerable<DataModel> data = this.Data .GroupBy(g => /* 这里是正则匹配逻辑 */) .Select(s => new DataModel { CallerNumber = s.Key, Duration = TimeSpan.FromTicks(s.Sum(c => c.Duration.Ticks)), }) .Where(w => !string.IsNullOrEmpty(w.CallerNumber)) .OrderByDescending(o => o.Duration);
我知道用.Take(10)能取前10条,但不知道怎么把剩下的项合并成‘Rest’部分——也就是取前10条后,把第11条及以后的项合并成输出列表的第11项。
解决方案
可以通过拆分前N项和剩余项、单独计算剩余项总时长、合并结果的方式实现,完整的LINQ查询如下:
int topCount = 10; // 可根据需求调整数量,比如示例中的3 var groupedData = this.Data .GroupBy(g => /* 这里是正则匹配逻辑 */) .Select(s => new DataModel { CallerNumber = s.Key, Duration = TimeSpan.FromTicks(s.Sum(c => c.Duration.Ticks)), }) .Where(w => !string.IsNullOrEmpty(w.CallerNumber)) .OrderByDescending(o => o.Duration) .ToList(); // 先把分组结果加载到内存,避免多次枚举数据源 // 取Top N项 var topItems = groupedData.Take(topCount); // 计算剩余项的总时长,生成Rest项 var restItems = groupedData.Skip(topCount); var restItem = new DataModel { CallerNumber = "Rest", Duration = TimeSpan.FromTicks(restItems.Sum(item => item.Duration.Ticks)) }; // 合并结果:仅当有剩余项时才添加Rest,避免空项 var finalData = topItems.Concat(restItems.Any() ? new[] { restItem } : Enumerable.Empty<DataModel>());
示例验证
用你提供的测试数据:
050321 4:30 045345 2:00 050321 4:00 045345 6:00 076843 1:00 050321 1:00 032345 3:00 043453 2:00 032345 3:00
设置topCount = 3,运行上述代码后,最终输出结果和预期一致:
050321 9:30 045345 8:00 032345 6:00 Rest 3:00
注意事项
- 调用
.ToList()是为了避免多次枚举原始数据源(如果数据源是EF等IQueryable,多次枚举会触发多次数据库查询); - 如果剩余项为空(即分组结果总数≤N),则不会添加Rest项,避免多余的空数据;
- 可根据需求灵活调整
topCount的值。
内容的提问来源于stack exchange,提问作者10101
相关产品推荐
相关产品推荐

