如何用最短方式或LINQ查询移除分组列表中的非连续行?
移除LINQ分组后不连续SequenceId记录的解决方案
你已经通过LINQ获取了按SequenceSource分组、且每组内按SequenceId升序排序的List<List<InboxProcessingDto>>,需求是移除每组中从第一个元素开始出现断连的后续记录,只保留开头的连续序列(例如SequenceId为22、23、27、28的组仅保留22、23;2、3、17、28、29的组仅保留2、3)。
实现思路
由于每组数据已按SequenceId排序,我们只需保留从第一个元素开始的最长连续序列:
- 以组内第一个元素的
SequenceId为基准 - 每个连续元素的
SequenceId应等于基准Id + 元素在序列中的索引 - 一旦遇到不满足该条件的元素,后续所有元素均为断连部分,直接截断
修改后的完整LINQ查询
await _context.Inboxes .Join(_context.InboxProcessingOffsets, x => x.SequenceSource, y => y.Source, (x, y) => new InboxProcessingDto { Inbox = x, InboxProcessingOffset = y }) .Where(i => i.Inbox.Status == InboxStatus.New) .Take(100) .ToListAsync() .ContinueWith(t => t.Result .GroupBy(i => i.Inbox.SequenceSource) .Select(grp => { var sortedItems = grp.OrderBy(i => i.Inbox.SequenceId).ToList(); if (!sortedItems.Any()) return sortedItems; var baseSeqId = sortedItems[0].Inbox.SequenceId; // 找到第一个断连的元素索引 var breakPoint = sortedItems.FindIndex((item, idx) => item.Inbox.SequenceId != baseSeqId + idx); // 若全部连续则返回完整列表,否则返回断点前的元素 return breakPoint == -1 ? sortedItems : sortedItems.Take(breakPoint).ToList(); }) .ToList());
代码说明
- 先通过
ToListAsync()异步获取初始数据集,再通过ContinueWith处理分组和连续序列过滤(避免在EF查询中使用客户端无法转换的逻辑) - 对每个分组:
- 排序并转为
List以便后续索引操作 - 空分组直接返回
- 用
FindIndex定位第一个不满足连续条件的元素位置 - 根据断点位置返回对应的连续子列表
- 排序并转为
内容的提问来源于stack exchange,提问作者Dreamer
相关产品推荐
相关产品推荐

