You need to enable JavaScript to run this app. 如何快速查找存在于列表B但不存在于列表A的人员(C# LINQ场景)
优惠活动
大模型
产品
解决方案
定价
更多

如何快速查找存在于列表B但不存在于列表A的人员(C# LINQ场景)

性能慢的根因

你当前的写法时间复杂度是O(n*m),n是listofPersons的长度,m是allUsedPersons的长度:每遍历1个listofPersons里的人员,都要完整遍历一遍allUsedPersons的所有元素判断Id是否匹配,当两个列表数据量稍大时,耗时会呈指数级增长。

优化方案

方案1:用HashSet存已使用人员Id(最通用、改造成本最低)

利用HashSet的O(1)查找特性,把整体时间复杂度降到O(n+m),数据量越大性能提升越明显,代码示例:

// 先把所有已使用人员的Id存入HashSet,仅需遍历一次allUsedPersons
var usedIdSet = new HashSet<int>(allUsedPersons.Select(p => p.Id));
// 遍历listofPersons时直接查HashSet,每次查找都是O(1)
var missingPeople = listofPersons.Where(p => !usedIdSet.Contains(p.Id)).ToList();

方案2:用LINQ的Except方法(代码更简洁,适合复用场景)

如果需要多处用到按Id判断人员相等的逻辑,可以自定义比较器,调用原生Except方法,内部实现也是基于HashSet,性能和方案1一致:
首先自定义Id比较器:

public class PersonIdEqualityComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y) => x?.Id == y?.Id;
    public int GetHashCode(Person obj) => obj?.Id.GetHashCode() ?? 0;
}

调用代码:

var missingPeople = listofPersons.Except(allUsedPersons, new PersonIdEqualityComparer()).ToList();

特殊场景补充

如果两个列表是直接从数据库查询出来的,不要先把全量数据拉到内存再过滤,直接在EF/EF Core查询阶段做过滤,生成NOT EXISTS的SQL在数据库层面执行,性能会更高:

var missingPeople = await dbContext.ListOfPersons
    .Where(p => !dbContext.AllUsedPersons.Any(a => a.Id == p.Id))
    .ToListAsync();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 02:18:00