C# 托利斯特(); } 非管理器4.Dump(); watch1.Stop(); Console.WriteLine(“HashSet:+watch1.elapsedmillisons”); watch1.Restart(); 列表非管理者5=新列表(); foreach(可枚举范围中的var项(最大值为1)) { bool[]test=newbool[managers.Max(x=>x.EmployeeId)+1]; foreach(管理者中的var管理者) { test[manager.EmployeeId]=true; } 非管理者5=员工。其中(x=>x.Id>test.Length-1 | |!test[x.Id])。ToList(); } 非管理器5.Dump(); watch1.Stop(); Console.WriteLine(“本机数组调用:”+watch1.elapsedmillisons); watch1.Restart(); 列表非管理器6=新列表(); foreach(可枚举范围中的var项(最大值为1)) { bool[]test=newbool[managers.Max(x=>x.EmployeeId)+1]; foreach(管理者中的var管理者) { test[manager.EmployeeId]=true; } 非管理者6=员工。其中(x=>x.Id>test.Length-1 | |!test[x.Id])。ToList(); } 非管理器6.Dump(); watch1.Stop(); WriteLine(“本机数组调用2:+watch1.elapsedmillisons”); } 公营雇员 { 公共int Id{get;set;} 公共字符串名称{get;set;} } 公共班级经理 { public int EmployeeId{get;set;} }

C# 托利斯特(); } 非管理器4.Dump(); watch1.Stop(); Console.WriteLine(“HashSet:+watch1.elapsedmillisons”); watch1.Restart(); 列表非管理者5=新列表(); foreach(可枚举范围中的var项(最大值为1)) { bool[]test=newbool[managers.Max(x=>x.EmployeeId)+1]; foreach(管理者中的var管理者) { test[manager.EmployeeId]=true; } 非管理者5=员工。其中(x=>x.Id>test.Length-1 | |!test[x.Id])。ToList(); } 非管理器5.Dump(); watch1.Stop(); Console.WriteLine(“本机数组调用:”+watch1.elapsedmillisons); watch1.Restart(); 列表非管理器6=新列表(); foreach(可枚举范围中的var项(最大值为1)) { bool[]test=newbool[managers.Max(x=>x.EmployeeId)+1]; foreach(管理者中的var管理者) { test[manager.EmployeeId]=true; } 非管理者6=员工。其中(x=>x.Id>test.Length-1 | |!test[x.Id])。ToList(); } 非管理器6.Dump(); watch1.Stop(); WriteLine(“本机数组调用2:+watch1.elapsedmillisons”); } 公营雇员 { 公共int Id{get;set;} 公共字符串名称{get;set;} } 公共班级经理 { public int EmployeeId{get;set;} },c#,linq,linq-to-objects,C#,Linq,Linq To Objects,如果您留下来加入项目并使用空条件进行筛选,效果会更好 void Main() { var employees = new[] { new Employee { Id = 20, Name = "Bob" }, new Employee { Id = 10, Name = "Kirk NM" }, new Employee { Id = 48, Name = "Rick NM" }, new Employee { Id

如果您留下来加入项目并使用空条件进行筛选,效果会更好

void Main()
{
    var employees = new[]
    {
        new Employee { Id = 20, Name = "Bob" },
        new Employee { Id = 10, Name = "Kirk NM" },
        new Employee { Id = 48, Name = "Rick NM" },
        new Employee { Id = 42, Name = "Dick" },
        new Employee { Id = 43, Name = "Harry" },
        new Employee { Id = 44, Name = "Joe" },
        new Employee { Id = 45, Name = "Steve NM" },
        new Employee { Id = 46, Name = "Jim NM" },
        new Employee { Id = 30, Name = "Frank"},
        new Employee { Id = 47, Name = "Dave NM" },
        new Employee { Id = 49, Name = "Alex NM" },
        new Employee { Id = 50, Name = "Phil NM" },
        new Employee { Id = 51, Name = "Ed NM" },
        new Employee { Id = 52, Name = "Ollie NM" },
        new Employee { Id = 41, Name = "Bill" },
        new Employee { Id = 53, Name = "John NM" },
        new Employee { Id = 54, Name = "Simon NM" }
    };

    var managers = new[]
    {
        new Manager { EmployeeId = 20 },
        new Manager { EmployeeId = 30 },
        new Manager { EmployeeId = 41 },
        new Manager { EmployeeId = 42 },
        new Manager { EmployeeId = 43 },
        new Manager { EmployeeId = 44 }
    };

    System.Diagnostics.Stopwatch watch1 = new System.Diagnostics.Stopwatch();

    int max = 1000000;

    watch1.Start();
    List<Employee> nonManagers1 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        nonManagers1 = (from employee in employees where !(managers.Any(x => x.EmployeeId == employee.Id)) select employee).ToList();

    }
    nonManagers1.Dump();
    watch1.Stop();
    Console.WriteLine("Any: " + watch1.ElapsedMilliseconds);

    watch1.Restart();       
    List<Employee> nonManagers2 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        nonManagers2 =
        (from employee in employees
        join manager in managers
            on employee.Id equals manager.EmployeeId
        into tempManagers
        from manager in tempManagers.DefaultIfEmpty()
        where manager == null
        select employee).ToList();
    }
    nonManagers2.Dump();
    watch1.Stop();
    Console.WriteLine("temp table: " + watch1.ElapsedMilliseconds);

    watch1.Restart();       
    List<Employee> nonManagers3 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        nonManagers3 = employees.Except(employees.Join(managers, e => e.Id, m => m.EmployeeId, (e, m) => e)).ToList();
    }
    nonManagers3.Dump();
    watch1.Stop();
    Console.WriteLine("Except: " + watch1.ElapsedMilliseconds);

    watch1.Restart();       
    List<Employee> nonManagers4 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        HashSet<int> managerIds = new HashSet<int>(managers.Select(x => x.EmployeeId));
        nonManagers4 = employees.Where(x => !managerIds.Contains(x.Id)).ToList();

    }
    nonManagers4.Dump();
    watch1.Stop();
    Console.WriteLine("HashSet: " + watch1.ElapsedMilliseconds);

      watch1.Restart();
      List<Employee> nonManagers5 = new List<Employee>();
      foreach (var item in Enumerable.Range(1, max))
      {
                   bool[] test = new bool[managers.Max(x => x.EmployeeId) + 1];
                   foreach (var manager in managers)
                   {
                        test[manager.EmployeeId] = true;
                   }

                   nonManagers5 = employees.Where(x => x.Id > test.Length - 1 || !test[x.Id]).ToList();


      }
      nonManagers5.Dump();
      watch1.Stop();
      Console.WriteLine("Native array call: " + watch1.ElapsedMilliseconds);

      watch1.Restart();
      List<Employee> nonManagers6 = new List<Employee>();
      foreach (var item in Enumerable.Range(1, max))
      {
                   bool[] test = new bool[managers.Max(x => x.EmployeeId) + 1];
                   foreach (var manager in managers)
                   {
                        test[manager.EmployeeId] = true;
                   }

                   nonManagers6 = employees.Where(x => x.Id > test.Length - 1 || !test[x.Id]).ToList();
      }
      nonManagers6.Dump();
      watch1.Stop();
      Console.WriteLine("Native array call 2: " + watch1.ElapsedMilliseconds);
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Manager
{
    public int EmployeeId { get; set; }
}

经理也是员工!因此,
Manager
类应该从
Employee
类中进行子类化(或者,如果您不喜欢,那么他们应该从父类中进行子类化,或者创建一个
非Manager
类)

然后,您的问题很简单,只需在
Employee
超类上实现
IEquatable
接口(对于
GetHashCode
,只需返回
EmployeeID
),然后使用以下代码:

var finalcertificates = (from globCert in resultCertificate
                                         join toExcludeCert in certificatesToExclude
                                             on globCert.CertificateId equals toExcludeCert.CertificateId into certs
                                         from toExcludeCert in certs.DefaultIfEmpty()
                                         where toExcludeCert == null
                                         select globCert).Union(currentCertificate).Distinct().OrderBy(cert => cert.CertificateName);

不能保证EmployeeId将匹配数组中的employee索引…好主意-我没有想到选择ID,以便除了使用默认的相等比较器外,将比较整数。然而,Levesque先生是正确的,我更新了示例以反映这一点。你能提供一个正确返回employees的例子吗?(我删除了我之前的评论-gWiz是正确的;这将起作用。)这将比其他方法的性能差得多,因为
employees.Single
O(n)
。请参阅(忽略第二个解决方案,使用HashSet-one,它更优越)。+1-很好。我对这个稍加修改,并将其纳入我的问题中。不过,我想看看其他人有什么想法。谢谢谢谢最初是在这里发现的:except函数只适用于两组相同对象类型,但不会直接应用于他的员工和经理示例。因此,我在回答中使用了重载方法。事实上,与其他解决方案相比,我更喜欢这种方法——我发现它的含义更清楚。出于个人偏好,我重写了join-in查询语法(请参阅问题中修订的示例代码)。非常感谢。当涉及到一个大集合时,除了速度太慢。加入答案是最好的。数据不错!非常感谢。如果您的员工和经理的ID非常高,比如说,在10万年代,那么您的稀疏阵列解决方案将彻底失败。没有任何东西表明ID不能这么高——它们是整数,我认为最好编写没有像这样奇怪的边缘情况的代码。@ErikE我不确定你的意思是什么。OP提供的数据是问题的一部分&我已经确定了处理这些数据的6种备选方法。如果数据不同,则不同的选项可能会更优化。有没有一个答案最适用于所有可能的数据集?如果有的话,我会非常感激你把它布置好让我将来可以使用它。想象一下,如果稀疏数组解决方案得到一个
Int32.Max
值,突然导致它占用8 Gb内存?HashSet解决方案非常优秀,如果您得到虚假的高ID值,它不会崩溃。当您说“数据不同”时,我认为不应该包括声明(或隐式)数据类型域中的值。除非另外指定为smallint(例如),否则应假定ID为4字节长的整数(带符号的Int32)。数据类型域内的任何值都不是“不同的数据”;不过,这只是一个经过消毒的例子。查找不匹配项的一般问题是一个很好的解决方案。不过,这可能是许多一般问题的一个很好的解决方案!如果两个不同的对象可以以某种方式合并,那么它们可能共享一个可以通过超类/子类表示的关系。在本例中,经理与员工之间存在“是-是”关系,因此使用继承非常有意义。“Has-a”关系不太可能受我建议的解决方案的影响(但不一定如此,因为生命周期和角色可能很难正确建模,开发人员有时可能会错过“is-a”关系)。
var nonmanagers = employees.Select(e => e.Id)
    .Except(managers.Select(m => m.EmployeeId))
    .Select(id => employees.Single(e => e.Id == id));
var nonManagers = ( from e1 in employees select e1 ).Except( from m in managers from e2 in employees where m.EmployeeId == e2.Id select e2 );
employees.Except(employees.Join(managers, e => e.Id, m => m.EmployeeId, (e, m) => e));
HashSet<int> managerIds = new HashSet<int>(managers.Select(x => x.EmployeeId));
nonManagers4 = employees.Where(x => !managerIds.Contains(x.Id)).ToList();
void Main()
{
    var employees = new[]
    {
        new Employee { Id = 20, Name = "Bob" },
        new Employee { Id = 10, Name = "Kirk NM" },
        new Employee { Id = 48, Name = "Rick NM" },
        new Employee { Id = 42, Name = "Dick" },
        new Employee { Id = 43, Name = "Harry" },
        new Employee { Id = 44, Name = "Joe" },
        new Employee { Id = 45, Name = "Steve NM" },
        new Employee { Id = 46, Name = "Jim NM" },
        new Employee { Id = 30, Name = "Frank"},
        new Employee { Id = 47, Name = "Dave NM" },
        new Employee { Id = 49, Name = "Alex NM" },
        new Employee { Id = 50, Name = "Phil NM" },
        new Employee { Id = 51, Name = "Ed NM" },
        new Employee { Id = 52, Name = "Ollie NM" },
        new Employee { Id = 41, Name = "Bill" },
        new Employee { Id = 53, Name = "John NM" },
        new Employee { Id = 54, Name = "Simon NM" }
    };

    var managers = new[]
    {
        new Manager { EmployeeId = 20 },
        new Manager { EmployeeId = 30 },
        new Manager { EmployeeId = 41 },
        new Manager { EmployeeId = 42 },
        new Manager { EmployeeId = 43 },
        new Manager { EmployeeId = 44 }
    };

    System.Diagnostics.Stopwatch watch1 = new System.Diagnostics.Stopwatch();

    int max = 1000000;

    watch1.Start();
    List<Employee> nonManagers1 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        nonManagers1 = (from employee in employees where !(managers.Any(x => x.EmployeeId == employee.Id)) select employee).ToList();

    }
    nonManagers1.Dump();
    watch1.Stop();
    Console.WriteLine("Any: " + watch1.ElapsedMilliseconds);

    watch1.Restart();       
    List<Employee> nonManagers2 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        nonManagers2 =
        (from employee in employees
        join manager in managers
            on employee.Id equals manager.EmployeeId
        into tempManagers
        from manager in tempManagers.DefaultIfEmpty()
        where manager == null
        select employee).ToList();
    }
    nonManagers2.Dump();
    watch1.Stop();
    Console.WriteLine("temp table: " + watch1.ElapsedMilliseconds);

    watch1.Restart();       
    List<Employee> nonManagers3 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        nonManagers3 = employees.Except(employees.Join(managers, e => e.Id, m => m.EmployeeId, (e, m) => e)).ToList();
    }
    nonManagers3.Dump();
    watch1.Stop();
    Console.WriteLine("Except: " + watch1.ElapsedMilliseconds);

    watch1.Restart();       
    List<Employee> nonManagers4 = new List<Employee>();
    foreach (var item in Enumerable.Range(1,max))
    {
        HashSet<int> managerIds = new HashSet<int>(managers.Select(x => x.EmployeeId));
        nonManagers4 = employees.Where(x => !managerIds.Contains(x.Id)).ToList();

    }
    nonManagers4.Dump();
    watch1.Stop();
    Console.WriteLine("HashSet: " + watch1.ElapsedMilliseconds);

      watch1.Restart();
      List<Employee> nonManagers5 = new List<Employee>();
      foreach (var item in Enumerable.Range(1, max))
      {
                   bool[] test = new bool[managers.Max(x => x.EmployeeId) + 1];
                   foreach (var manager in managers)
                   {
                        test[manager.EmployeeId] = true;
                   }

                   nonManagers5 = employees.Where(x => x.Id > test.Length - 1 || !test[x.Id]).ToList();


      }
      nonManagers5.Dump();
      watch1.Stop();
      Console.WriteLine("Native array call: " + watch1.ElapsedMilliseconds);

      watch1.Restart();
      List<Employee> nonManagers6 = new List<Employee>();
      foreach (var item in Enumerable.Range(1, max))
      {
                   bool[] test = new bool[managers.Max(x => x.EmployeeId) + 1];
                   foreach (var manager in managers)
                   {
                        test[manager.EmployeeId] = true;
                   }

                   nonManagers6 = employees.Where(x => x.Id > test.Length - 1 || !test[x.Id]).ToList();
      }
      nonManagers6.Dump();
      watch1.Stop();
      Console.WriteLine("Native array call 2: " + watch1.ElapsedMilliseconds);
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Manager
{
    public int EmployeeId { get; set; }
}
var finalcertificates = (from globCert in resultCertificate
                                         join toExcludeCert in certificatesToExclude
                                             on globCert.CertificateId equals toExcludeCert.CertificateId into certs
                                         from toExcludeCert in certs.DefaultIfEmpty()
                                         where toExcludeCert == null
                                         select globCert).Union(currentCertificate).Distinct().OrderBy(cert => cert.CertificateName);
var nonManagerEmployees = employeeList.Except(managerList);