C# 获取两个列表之间的差异

C# 获取两个列表之间的差异,c#,.net,linq,C#,.net,Linq,我有两个列表(ListA和ListB),这些列表的类型是相同的PersonInfo,Login字段是唯一的键 public class PersonInfo { public string Login { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public bool

我有两个列表(
ListA
ListB
),这些列表的类型是相同的
PersonInfo
Login
字段是唯一的键

public class PersonInfo
{
    public string Login { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public bool Active { get; set; }
}
我想比较一下这两个列表:

  • 我想在
    ListA
    中获得
    ListB
    中不可用的项目列表

  • 对于两个列表中可用的项目,我希望从
    ListA
    Login
    字段是唯一的键)获取两个列表之间存在差异的项目的列表

  • 示例:如果对于
    ListA
    中的
    Login
    “MyLogin”,则
    FirstName
    的值与
    ListB
    中的值不匹配。“MyLogin”为登录名的项目必须是结果列表的一部分

    示例:如果特定登录名的
    ListA
    ListB
    之间的
    Age
    不同,则该项必须是结果的一部分

    谢谢。

    编辑

    请尝试此解决方案以了解细节差异:


    -使用默认相等比较器比较值,生成两个序列的集合差

           double[] numbers1 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };
            double[] numbers2 = { 2.2 };
    
            IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
    

    您可以使用LINQ中的Zip()和Intersect()来比较自定义数据类型列表的对象,您需要在类中实现
    IEquatable
    ,并重写
    GetHashCode()

    检查这个

    你们班

        public class PersonInfo : IEquatable<PersonInfo>
        {
            public string Login { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int Age { get; set; }
            public bool Active { get; set; }
    
            public bool Equals(PersonInfo other)
            {
                //Check whether the compared object is null.
                if (Object.ReferenceEquals(other, null)) return false;
    
                //Check whether the compared object references the same data.
                if (Object.ReferenceEquals(this, other)) return true;
    
                //Check whether the properties are equal.
                return Login.Equals(other.Login) && FirstName.Equals(other.FirstName) && LastName.Equals(other.LastName) && Age.Equals(other.Age) && Active.Equals(other.Active);
            }
    
            public override int GetHashCode()
            {
    
                int hashLogin = Login == null ? 0 : Login.GetHashCode();
    
                int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
    
                int hashLastName = LastName == null ? 0 : LastName.GetHashCode();
    
                int hashAge = Age.GetHashCode();
    
                int hashActive = Active.GetHashCode();
    
                //Calculate the hash code.
                return (hashLogin + hashFirstName + hashLastName) ^ (hashAge + hashActive);
            }
        }
    
    公共类PersonInfo:IEquatable
    {
    公共字符串登录{get;set;}
    公共字符串名{get;set;}
    公共字符串LastName{get;set;}
    公共整数{get;set;}
    公共bool活动{get;set;}
    公共布尔等于(PersonInfo其他)
    {
    //检查比较对象是否为空。
    if(Object.ReferenceEquals(other,null))返回false;
    //检查比较对象是否引用相同的数据。
    if(Object.ReferenceEquals(this,other))返回true;
    //检查属性是否相等。
    返回Login.Equals(other.Login)&&FirstName.Equals(other.FirstName)&&LastName.Equals(other.LastName)&&Age.Equals(other.Age)&&Active.Equals(other.Active);
    }
    公共覆盖int GetHashCode()
    {
    int hashLogin=Login==null?0:Login.GetHashCode();
    int hashFirstName=FirstName==null?0:FirstName.GetHashCode();
    int hashLastName=LastName==null?0:LastName.GetHashCode();
    int hashAge=Age.GetHashCode();
    int hashActive=Active.GetHashCode();
    //计算散列码。
    返回(hashLogin+hashFirstName+hashLastName)^(hashAge+hashActive);
    }
    }
    
    下面是您如何使用它(如Pranay的回复中所列)

    List List a=new List(){new PersonInfo{Login=“1”,FirstName=“James”,LastName=“Watson”,Active=true,Age=21},new PersonInfo{Login=“2”,FirstName=“Jane”,LastName=“Morrison”,Active=true,Age=25},new PersonInfo{Login=“3”,FirstName=“Kim”,LastName=“John”,Active=false,Age=33};
    List ListB=new List(){new PersonInfo{Login=“1”,FirstName=“James2222”,LastName=“Watson”,Active=true,Age=21},new PersonInfo{Login=“3”,FirstName=“Kim”,LastName=“John”,Active=false,Age=33};
    //获取ListA中不在ListB中的项
    List FilteredListA=ListA.Except(ListB.ToList();
    //获取ListA和FilteredListA之间的差异(FilteredListA中的项目将从ListA中删除)
    RemoveAll(a=>FilteredListA.Contains(a));
    
    尝试此方法进行对象比较,并在
    列表中循环

    publicstaticvoid GetPropertyChanges(这个T oldObj,T newObj)
    {
    类型=类型(T);
    foreach(type.GetProperties中的System.Reflection.PropertyInfo pi(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
    {
    对象selfValue=type.GetProperty(pi.Name).GetValue(oldObj,null);
    objecttovalue=type.GetProperty(pi.Name).GetValue(newObj,null);
    if(selfValue!=null&&toValue!=null)
    {
    if(selfValue.ToString()!=toValue.ToString())
    {
    //做你的代码
    }
    }
    }
    }
    
    无论如何,我都会得到我想要的结果。1.如果ListA有3个项目,ListB有2个项目,那么在结果中我看不到缺少的项目。2.如果两个列表中都有3个项目(两侧的登录匹配),如何比较每个属性?(RemoveAll未出现在intellisense中)抱歉,但结果中仍有3项,而不是difference@Kris-我-嗨,检查我的编辑答案粘贴的链接…去那个链接有答案帮助你获得细节差异。。。
    var compare1to2 = from a in 
               from b in driveList2.Where(b => b.property == a.property).DefaultIfEmpty()
                                  select a;
    
        public class PersonInfo : IEquatable<PersonInfo>
        {
            public string Login { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int Age { get; set; }
            public bool Active { get; set; }
    
            public bool Equals(PersonInfo other)
            {
                //Check whether the compared object is null.
                if (Object.ReferenceEquals(other, null)) return false;
    
                //Check whether the compared object references the same data.
                if (Object.ReferenceEquals(this, other)) return true;
    
                //Check whether the properties are equal.
                return Login.Equals(other.Login) && FirstName.Equals(other.FirstName) && LastName.Equals(other.LastName) && Age.Equals(other.Age) && Active.Equals(other.Active);
            }
    
            public override int GetHashCode()
            {
    
                int hashLogin = Login == null ? 0 : Login.GetHashCode();
    
                int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
    
                int hashLastName = LastName == null ? 0 : LastName.GetHashCode();
    
                int hashAge = Age.GetHashCode();
    
                int hashActive = Active.GetHashCode();
    
                //Calculate the hash code.
                return (hashLogin + hashFirstName + hashLastName) ^ (hashAge + hashActive);
            }
        }
    
                List<PersonInfo> ListA = new List<PersonInfo>() { new PersonInfo { Login = "1", FirstName = "James", LastName = "Watson", Active = true, Age = 21 }, new PersonInfo { Login = "2", FirstName = "Jane", LastName = "Morrison", Active = true, Age = 25 }, new PersonInfo { Login = "3", FirstName = "Kim", LastName = "John", Active = false, Age = 33 } };
                List<PersonInfo> ListB = new List<PersonInfo>() { new PersonInfo { Login = "1", FirstName = "James2222", LastName = "Watson", Active = true, Age = 21 }, new PersonInfo { Login = "3", FirstName = "Kim", LastName = "John", Active = false, Age = 33 } };
    
                //Get Items in ListA that are not in ListB
                List<PersonInfo> FilteredListA = ListA.Except(ListB).ToList();
    
                //To get the difference between ListA and FilteredListA (items from FilteredListA will be removed from ListA)
                ListA.RemoveAll(a => FilteredListA.Contains(a));
    
    var list3 = list1.Except(list2).ToList(); //List3 contains what in list1 but not _list2.
    
    public static void GetPropertyChanges<T>(this T oldObj, T newObj)
    {
        Type type = typeof(T);
        foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
        {
            object selfValue = type.GetProperty(pi.Name).GetValue(oldObj, null);
            object toValue = type.GetProperty(pi.Name).GetValue(newObj, null);
            if (selfValue != null && toValue != null)
            {
                if (selfValue.ToString() != toValue.ToString())
                {
                    //do your code
                }
            }
        }
    }