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

如何使用Linq在C#中过滤两个不同模型列表的差异数据

使用LINQ找出两个列表的差异内容

当然可以用LINQ实现这个需求!你当前用Join只能拿到两个列表中匹配的元素,但我们要的是差异项——也就是lstComplete里那些没出现在lstAssigned中的路由属性。

不过这里得先明确:判断两个元素是否“匹配”的依据是什么?从你的模型来看,RoutingAttributeModel和AgentRoutingAttributeModel都有Bus_No和Attribute_No,通常这两个字段应该是联合唯一标识,所以建议用这两个字段一起判断匹配(避免不同Bus下的同Attribute_No被误判)。如果确实只需要用Attribute_No,后面的代码你可以自行调整条件。

下面给你几种实用的实现方式:

方法1:Where + Any(最直观易懂)

这种方式直接遍历lstComplete,筛选出在lstAssigned中找不到对应匹配项的元素:

// 基于Bus_No和Attribute_No联合判断的差异项
var unassignedAttributes = lstComplete
    .Where(cl => !lstAssigned.Any(al => al.Bus_No == cl.Bus_No && al.Attribute_No == cl.Attribute_No))
    .ToList();

如果只需要按Attribute_No判断,把条件改成al.Attribute_No == cl.Attribute_No就行。

方法2:Except(更简洁,但需要自定义比较器)

Except方法可以直接返回两个集合的差集,但因为我们用的是自定义类,得先实现一个IEqualityComparer来定义“相等”的规则:

// 定义比较器类,用于判断两个RoutingAttributeModel是否相等
public class RoutingAttributeComparer : IEqualityComparer<RoutingAttributeModel>
{
    public bool Equals(RoutingAttributeModel x, RoutingAttributeModel y)
    {
        if (x == null || y == null) return false;
        // 这里用联合字段判断,你也可以改成只判断Attribute_No
        return x.Bus_No == y.Bus_No && x.Attribute_No == y.Attribute_No;
    }

    public int GetHashCode(RoutingAttributeModel obj)
    {
        // 对应Equals的规则生成哈希码,确保哈希值一致
        return HashCode.Combine(obj.Bus_No, obj.Attribute_No);
    }
}

然后把lstAssigned转换成RoutingAttributeModel类型,再用Except求差集:

// 先把Agent的分配列表转换成完整属性模型的格式
var assignedAsComplete = lstAssigned.Select(al => new RoutingAttributeModel
{
    Bus_No = al.Bus_No,
    Attribute_No = al.Attribute_No,
    Attribute_Name = al.Attribute_Name,
    Status = al.Status,
    Notes = null // Agent模型没有Notes字段,这里设为null即可
}).ToList();

// 求差集:lstComplete里有但assignedAsComplete里没有的元素
var unassignedAttributes = lstComplete.Except(assignedAsComplete, new RoutingAttributeComparer()).ToList();

方法3:左外连接(延续你之前的Join思路)

你之前尝试了Join,其实用左外连接可以直接拿到所有lstComplete的元素,以及匹配的lstAssigned元素,然后筛选出没有匹配的那些:

var unassignedAttributes = from cl in lstComplete
                           // 用匿名类型做联合键关联两个列表
                           join al in lstAssigned 
                           on new { cl.Bus_No, cl.Attribute_No } equals new { al.Bus_No, al.Attribute_No } into joinedGroup
                           // 左外连接:如果没有匹配项,al会是null
                           from al in joinedGroup.DefaultIfEmpty()
                           // 筛选出没有匹配的元素
                           where al == null
                           select cl;

这种写法和方法1的效果完全一致,只是用LINQ查询表达式的方式实现,更贴近你之前的尝试。

补充:如果需要双向差异

要是你需要的是双向差异(也就是lstComplete里有但lstAssigned没有的,加上lstAssigned里有但lstComplete没有的),可以把两个方向的差集合并:

// 先找lstComplete里未被分配的
var completeNotAssigned = lstComplete.Where(cl => !lstAssigned.Any(al => al.Bus_No == cl.Bus_No && al.Attribute_No == cl.Attribute_No));
// 再找lstAssigned里不在lstComplete中的(可能是已删除的属性还在分配列表里)
var assignedNotComplete = lstAssigned.Where(al => !lstComplete.Any(cl => cl.Bus_No == al.Bus_No && cl.Attribute_No == al.Attribute_No));
// 合并两个结果(因为类型不同,转成object或者创建DTO类统一)
var fullDiff = completeNotAssigned.Cast<object>().Concat(assignedNotComplete.Cast<object>()).ToList();

内容的提问来源于stack exchange,提问作者Felix A. Zelaya O.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:47:54