获取两个列表之间的差异

3

我有两个列表(ListAListB),它们的类型相同都是 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; }
}

我想比较这两个列表:
  1. 我想得到在ListB中没有的ListA中的项目列表。

  2. 对于两个列表中都有的项目,我想从ListA中获取一个列表(Login字段是唯一的关键),其中两个列表之间存在差异的项目。

例如:如果在ListA中,对于Login“MyLogin”,FirstName的值与ListB中的值不匹配。带有“MyLogin”作为Login的项目必须包含在结果列表中。
例如:如果特定登录的ListAListB之间的Age不同,则该项目必须成为结果的一部分。
谢谢。
5个回答

5

要比较自定义数据类型列表中的对象,您需要在类中实现IEquatable并重写GetHashCode()方法。

请参阅此MSDN链接

您的类

    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);
        }
    }

那么这是如何使用它的(如Pranay的回答中列出的):
            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));

4

编辑

尝试此解决方案以获取详细差异: 比较两个对象并找出差异


如何:在两个列表之间查找集合差异 (LINQ)

Enumerable.Except 方法 (IEnumerable, IEnumerable) - 通过使用默认的相等比较器来比较值,生成两个序列的集合差异。

       double[] numbers1 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };
        double[] numbers2 = { 2.2 };

        IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);

或者
//newList will include all the common data between the 2 lists
List<T> newList = list1.Intersect(list2).ToList<T>();


//differences will be the data not found 
List<T> differences = list1.RemoveAll(a => newList.Contains(a));

使用外连接获取差异

var compare1to2 = from a in 
           from b in driveList2.Where(b => b.property == a.property).DefaultIfEmpty()
                              select a;

无论如何,我都能得到想要的结果。1. 如果ListA有3个项目,而ListB只有2个项目,在结果中我看不到缺失的那一个。2. 如果两个列表中都有3个项目(登录在双方都匹配),如何比较每个属性?(RemoveAll在智能感知中不出现) - TheBoubou
抱歉,但是结果仍然有3个项目,而不是差异。 - TheBoubou
@Kris-I - 嗨,请查看我编辑答案中粘贴的链接...点击该链接,里面有一个答案可以帮助你了解详细的区别... - Pranay Rana

2
var list3 = list1.Except(list2).ToList(); //List3 contains what in list1 but not _list2.

0

尝试使用此方法进行对象比较,并循环遍历List<T>

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
            }
        }
    }
}

-4

你可以使用LINQ中的Zip()和Intersect()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接