检查两个List <T>是否相等的最快方法

SKJ*_*SKJ 10 .net c#

我有两个列表

ListA<Emp>并且ListB<Emp> 两者都具有1000条记录.

Emp是Employee Class的一个对象.以下是我的Employee

public class Employee
{
    int ID = 0;
    string Name = String.Empty;
    string Dept = String.Empty;
    string Address = String.Empty;
    int Age = 0;
    string Email = String.Empty;
}
Run Code Online (Sandbox Code Playgroud)

我想验证两个列表是否相等.Emp对象可以按不同顺序放置.此外,可能有几个Emp对象在列表中具有完全相同的信息.我也必须核实这些.

我试图对列表进行排序并进行比较 SequenceEqual

Enumerable.SequenceEqual(ListA.OrderBy(s => s), ListB.OrderBy(s => s)
Run Code Online (Sandbox Code Playgroud)

我收到了以下错误

At least one object must implement IComparable.
Exception Stack trace is as below 

   at System.Collections.Comparer.Compare(Object a, Object b)
   at System.Collections.Generic.ObjectComparer`1.Compare(T x, T y)
   at System.Linq.EnumerableSorter`2.CompareKeys(Int32 index1, Int32 index2)
   at System.Linq.EnumerableSorter`1.QuickSort(Int32[] map, Int32 left, Int32 right)
   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
   at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__0.MoveNext()
   at System.Linq.Enumerable.SequenceEqual[TSource](IEnumerable`1 first, IEnumerable`1 second, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.SequenceEqual[TSource](IEnumerable`1 first, IEnumerable`1 second)
Run Code Online (Sandbox Code Playgroud)

我该如何实现呢?如果你们能够以最快的方式为我提供这样做会更好,因为List中的对象数量可能会增加到1000万.谢谢你的帮助 !

编辑:每个员工必须在两个列表中,顺序无关紧要.但是,如果ListA包含相同的雇员对象5次(这意味着一些重复的条目),并且ListB包含雇员对象4次,则ListA和ListB不相等.

Tim*_*ter 8

您可以使用SequenceEqual 自定义IEqualityComparer<Employee>:

class EmployeeComparer : IEqualityComparer<Employee>
{
    public bool Equals(Employee x, Employee y)
    {
        if (x == null || y == null) return false;

        bool equals = x.ID==y.ID && x.Name == y.Name && x.Dept == y.Dept 
            && x.Address == y.Address && x.Age == y.Age && x.Email == y.Email;
        return equals;
    }

    public int GetHashCode(Employee obj)
    {
        if (obj == null) return int.MinValue;

        int hash = 19;
        hash = hash + obj.ID.GetHashCode();
        hash = hash + obj.Name.GetHashCode();
        hash = hash + obj.Dept.GetHashCode();
        hash = hash + obj.Address.GetHashCode();
        hash = hash + obj.Age.GetHashCode();
        hash = hash + obj.Email.GetHashCode();
        return hash;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在它很简单:

listA.SequenceEqual(ListB, new EmployeeComparer());
Run Code Online (Sandbox Code Playgroud)

如果订单不重要且您只想知道所有员工是否都在两个列表中,您可以使用它HashSet<Employee>.SetEquals来确定两个列表是否包含相同的人员:

var empComparer =  new EmployeeComparer();
bool bothEqual = new HashSet<Employee>(ListA, empComparer)
      .SetEquals(new HashSet<Employee>(ListB, empComparer));
Run Code Online (Sandbox Code Playgroud)


Тол*_*оля 5

最佳复杂度是 O(N) 以下使用 HashSet 实现:

具有 GetHashCode 和 Equals 实现的类:

public class Employee
{
    public int ID = 0;
    public string Name = String.Empty;
    public string Dept = String.Empty;
    public string Address = String.Empty;
    public int Age = 0;
    public string Email = String.Empty;

    public override int GetHashCode()
    {
        return
            ID.GetHashCode() ^
            (Name ?? String.Empty).GetHashCode() ^
            (Dept ?? String.Empty).GetHashCode() ^
            (Address ?? String.Empty).GetHashCode() ^
            Age.GetHashCode() ^
            (Email ?? String.Empty).GetHashCode()
            ;
    }
    public override bool Equals(object obj)
    {
        Employee other = obj as Employee;
        if (obj == null)
            return false;

        return ID == other.ID &&
                Name == other.Name &&
                Dept == other.Dept &&
                Address == other.Address &&
                Age == other.Age &&
                Email == other.Email;
    }
}
Run Code Online (Sandbox Code Playgroud)

比较列表的函数:

public static bool CompareLists(List<Employee> list1, List<Employee> list2)
{
    if (list1 == null || list2 == null)
        return list1 == list2;

    if (list1.Count != list2.Count)
        return false;
    Dictionary<Employee, int> hash = new Dictionary<Employee, int>();
    foreach (Employee employee in list1)
    {
        if (hash.ContainsKey(employee))
        {
            hash[employee]++;
        }
        else
        {
            hash.Add(employee, 1);
        }
    }

    foreach (Employee employee in list2)
    {
        if (!hash.ContainsKey(employee) || hash[employee] == 0)
        {
            return false;
        }
        hash[employee]--;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)