c# – 使用LINQ.有两个不同的列表.如何识别不匹配的对象

前端之家收集整理的这篇文章主要介绍了c# – 使用LINQ.有两个不同的列表.如何识别不匹配的对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有三个班:
public partial class Objective{
    public Objective() {
        this.ObjectiveDetails = new List<ObjectiveDetail>();
    }
    public int ObjectiveId { get; set; }
    public int Number { get; set; }
    public virtual ICollection<ObjectiveDetail> ObjectiveDetails { get; set; }
}
public partial class ObjectiveDetail {
    public ObjectiveDetail() {
        this.SubTopics = new List<SubTopic>();
    }
    public int ObjectiveDetailId { get; set; }
    public int Number { get; set; }
    public string Text { get; set; }
    public virtual ICollection<SubTopic> SubTopics { get; set; }
}
public partial class SubTopic {
    public int SubTopicId { get; set; }
    public string Name { get; set; }
}

我有两个列表:

IList<ObjectiveDetail> oldObj;
IList<ObjectiveDetail> newObj;

以下LINQ给出了一个新的ObjectiveDetail对象列表,其中:列表中的任何ObjectiveDetail对象的Number或Text字段在oldObj和newObj之间是不同的.

IList<ObjectiveDetail> upd = newObj
    .Where(wb => oldObj
        .Any(db => (db.ObjectiveDetailId == wb.ObjectiveDetailId) && 
                   (db.Number != wb.Number || !db.Text.Equals(wb.Text))))
     .ToList();

我如何修改它,以便LINQ给我一个新的ObjectiveDetail对象列表,其中:列表中的任何ObjectiveDetail对象的Number或Text字段或SubTopic集合在oldObj和newObj之间是不同的.

换句话说,我想要一个ObjectiveDetail被添加到upd列表如果:

>它在oldObj中的文本与newObj中的文本不同
>它的oldObj中的Number与newObj中的Number不同
>它有一个SubTopics集合,在oldObj中有三个元素,在newObj中有4个元素
>它有一个SubTopics集合,在oldObj中没有元素,在newObj中没有2个元素
>它有一个SubTopics集合,在oldObj中有2个元素,在newObj中没有元素
>它有一个SubTopics集合,其中SubTopicId的元素在oldObj中为1和2,在newObj中为1和3

我希望有人可以提出我已经拥有的LINQ语句中的一些额外的一行.

解决方法

这应该是你需要的:
IList<ObjectiveDetail> upd = newObj.Where(wb =>
            oldObj.Any(db =>
                (db.ObjectiveDetailId == wb.ObjectiveDetailId) &&
                    (db.Number != wb.Number || !db.Text.Equals(wb.Text)
                    || db.SubTopics.Count != wb.SubTopics.Count
                    || !db.SubTopics.All(ds => wb.SubTopics.Any(ws =>
                                     ws.SubTopicId == ds.SubTopicId))
                    ))).ToList();

怎么运行的

db.SubTopics.Count!= wb.SubTopics.Count确认正在比较的新对象(wb)和被比较的旧对象(db)具有相同数量的SubTopics.那部分是非常简单的.

!db.SubTopics.All(ds => wb.SubTopics.Any(ws => ws.SubTopicId == ds.SubTopicId))有点复杂.如果给定的表达式对于集合的所有成员都为true,则All()方法返回true.如果给定的表达式对于集合中的任何成员都为true,那么Any()方法返回true.因此,整个表达式检查对于旧对象db中的每个SubTopic ds,在新对象wb中是否存在具有相同ID的Subtopic ws.

基本上,第二行确保在旧对象中存在的每个SubTopic也存在于新对象中.第一行确保旧的&新对象具有相同数量的SubTopics;否则第二行将考虑使用SubTopics 1& amp; 2与SubTopics 1,2,& 3.

注意事项

添加不会检查SubTopics是否具有相同的名称;如果还需要检查,那么将第二行中的ws.SubTopicId == ds.SubTopicId更改为ws.SubTopicId == ds.SubTopicId&&& ws.Name.Equals(ds.Name).

如果ObjectiveDetail可以包含多个具有相同SubTopicId的SubTopic(即,如果SubTopicIds不是唯一的),则此添加将无法正常工作.如果是这样,您需要用第二行替换db.SubTopics.All(ds => db.SubTopics.Count(ds2 => ds2.SubTopicId == ds.SubTopicId)== wb.SubTopics.Count (ws => ws.SubTopicId == ds.SubTopicId)).这将检查每个SubTopicId在新对象中的显示格式与旧对象中的完全一样多.

这个添加将不会检查SubTopics中的新对象&旧对象的顺序相同.为此,您将需要用db.SubTopics.Where((ds,i)=> ds.SubTopicId == wb.SubTopics [i] .SubTopicId).Count!= db.SubTopics.Count替换第二行.请注意,此版本还处理非唯一的SubTopicId值.它确认了旧对象中SubTopics的数量,使得新对象中相同位置的SubTopic相同等于旧对象中SubTopics的总数(也就是说,对于旧对象中的每个SubTopic,SubTopic在新对象中的相同位置是一样的).

高层思想

从可维护的角度来看,康拉德·科科萨(Konrad Kokosa)的答案是更好的(我已经被提拔了).如果您不期望需要经常重新访问该语句,我将只使用这样一个很丑的LINQ语句.如果您认为决定两个ObjectiveDetail对象是否相等的方式可能会更改,或者使用此语句的方法可能需要重新工作,否则该方法至关重要,因为第一次查看代码新用户需要能够快速了解​​它,那么不要使用大长串的LINQ.

猜你在找的C#相关文章