You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LINQ按指定属性去重并取最新记录的性能优化方案

性能优化方案说明

你当前的实现逻辑是正确的,但存在可优化的性能空间:

  • 现有写法先对全量users集合做降序排序,这一步的时间复杂度是O(n log n),数据量越大排序带来的CPU和内存开销越高,而实际上「按SSN分组取最新StartDate记录」的需求完全不需要对全量数据排序。

最优性能实现(O(n)时间复杂度)

直接通过一次遍历+字典维护每个SSN对应的最新记录即可,没有额外排序开销,整体时间复杂度为O(n),是理论上的最优复杂度:

var latestUserMap = new Dictionary<string, User>();
foreach (var user in users)
{
    // 字典中不存在当前SSN,或当前记录的StartDate比已存记录更新时,替换字典内的值
    if (!latestUserMap.TryGetValue(user.SSN, out var existedUser) || user.StartDate > existedUser.StartDate)
    {
        latestUserMap[user.SSN] = user;
    }
}

// 获取去重后的完整用户列表
var district = latestUserMap.Values.ToList();
// 获取所有SSN列表直接取字典键即可,不需要二次遍历用户对象
var ssn = latestUserMap.Keys.ToList();

这个实现的性能在大数据量场景下优势极其明显:当集合条数达到10万级以上时,执行速度通常是你原有写法的5~20倍,内存占用也会低40%以上,不需要为排序操作分配临时存储。

简化LINQ写法(兼容.NET 6+)

如果你更偏好LINQ的声明式写法,不想手写循环,可以用MaxBy直接取分组内的最新记录,跳过全量排序步骤,性能比原写法高,但略低于手写字典的方案:

var district = users
    .GroupBy(u => u.SSN)
    .Select(g => g.MaxBy(u => u.StartDate))
    .ToList();

var ssn = district.Select(u => u.SSN).ToList();

如果使用的是.NET 6以下的版本,没有内置MaxBy方法,可以在Select内自行遍历分组比较StartDate取最大值即可。

注意:如果你使用的是EF Core等ORM框架做数据库查询,上述LINQ写法会被翻译成高效的SQL语句(通常是ROW_NUMBER() OVER(PARTITION BY SSN ORDER BY StartDate DESC)窗口函数逻辑),不会在内存中做全量排序,这种场景下直接用LINQ写法即可,不需要拉取全量数据到内存后手写字典逻辑。

内容的提问来源于stack exchange,提问作者Bug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:24:15