查找其他列表中不存在的所有项目需要花费大量时间
本文关键字:时间 项目 列表 其他 不存在 查找 | 更新日期: 2023-09-27 18:26:26
我有两个通用列表,一个有70000多个项目,另一个有10个项目。当与第一个列表进行比较时,我必须找出第二个列表中不存在的项目。从逻辑上讲,我的代码运行良好,使用较小的列表集不会遇到任何严重的性能问题。由于我的第一个清单是超过70000个项目,我面临着严重的性能问题。执行和获得结果需要花费大量时间。
我的问题是?有更好的方法吗?我无法忍受这个性能问题。有什么改进的建议吗?我正在使用C#,.NET 3.5
List<Employee> existingEmployeeList = List of 70K employees;
List<Employee> validEmployeeList = List of 10 employees;
var emloyeeDeletedFilterList = existingEmployeeList.Where(m => !validEmployeeList.Any(p => p.EmployeeId == m.EmployeeId
&& p.FirstName == m.FirstName
&& p.Age == m.Age
&& p.LastName == m.LastName));
我还有其他操作要查找,这些操作是新添加到列表中的。
var emloyeeAddedFilterList = validEmployeeList.Where(m => !existingEmployeeList.Any(p => p.EmployeeId == m.EmployeeId
&& p.FirstName == m.FirstName
&& p.Age == m.Age
&& p.LastName == m.LastName));
我在where子句中有4个条件来筛选员工列表。
编辑了我的问题:又添加了一个代码片段
编写一个自定义EqualityComparer<Employee>
来比较您的4个字段,然后使用.Intersect(
进行
var emloyeeFilterList = validEmployeeList.Intersect(existingEmployeeList, new EmployeeComparer()).ToList();
我认为在validEmployeeList
而不是existingEmployeeList
上调用.Intersect(
会更快,但我会通过两种方式进行测试以确定。
更新:
哎呀,误解了你想要什么。您想要使用的查询是Except
,而不是Intersect
。
如果您想要除有效员工以外的所有现有员工
var emloyeeFilterList = existingEmployeeList.Execpt(validEmployeeList, new EmployeeComparer()).ToList();
或者如果您想要除现有员工之外的所有有效员工。
var emloyeeFilterList = validEmployeeList.Execpt(existingEmployeeList, new EmployeeComparer()).ToList();
这里还有一个如何编写EmployeeComparer
的示例
public class EmployeeComparer : EqualityComparer<Employee>
{
public override bool Equals(Employee x, Employee y)
{
return x.EmployeeId == y.EmployeeId
&& x.FirstName == y.FirstName
&& x.Age == y.Age
&& x.LastName == y.LastName
}
//Implmentation taken from http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
public override int GetHashCode(Employee obj)
{
unchecked // Overflow is fine, just wrap
{
int hash = (int) 2166136261;
// Suitable nullity checks etc, of course :)
hash = hash * 16777619 ^ obj.EmployeeId.GetHashCode();
hash = hash * 16777619 ^ obj.FirstName.GetHashCode();
hash = hash * 16777619 ^ obj.Age.GetHashCode();
hash = hash * 16777619 ^ obj.LastName.GetHashCode();
return hash;
}
}
}
考虑使用HashSet来存储元素。哈希集要求您重载类的哈希函数。
此外,CPU可以比任何其他类型更快地比较整数。在遍历元素时,请考虑实现更多的整数比较。
如果你对衡量性能感兴趣,请阅读关于评估程序相对性能的大O方法论。
节日快乐
对于我可以从您的代码示例中解释的内容,您似乎只需要检查"EmployeeId"。如果不是这样,您可以尝试以下操作来避免使用LinQ,因为它没有显式迭代那么快。
List<Employee> employeeFilterList = new List<Employee>();
for(int a = validEmployeeList.Count; --a >= 0; )
{
for(int b = existingFieldMappingList.Count; --b >= 0; )
{
Employee aEmployee = validEmployeeList[a];
Employee bEmployee = validEmployeeList[b];
if (aEmployee.EmployeeId != bEmployee.EmployeeId)
continue;
if (aEmployee.FirstName != bEmployee.FirstName)
continue;
if (aEmployee.Age != bEmployee.Age)
continue;
if (aEmployee.LastName != bEmployee.LastName)
continue;
employeeFilterList.Add(aEmployee);
}
}
编辑:请记住,您可以按照第一个条件最有可能跳到下一次迭代的方式重新排序IF条件。