查找另一个列表中不存在的所有项目需要很多时间
Find all items that are not there in another list takes lot of time
我有几个通用列表,一个有超过 70,000 个项目,另一个有 10 个项目。与第一个列表进行比较时,我必须找出第二个列表中不存在的项目。从逻辑上讲,我的代码运行良好,并且我不会遇到较小列表集的任何严重性能问题。由于我的第一个列表超过 70K 个项目,我面临着严重的性能问题。执行和得到结果需要很多时间。
我的问题是?有没有更好的方法来做到这一点?我无法忍受这个性能问题。有什么改进建议吗?我正在使用 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>
to compare on your 4 fields then use .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
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 来存储元素。 Hash Set 要求您重载 class 的哈希函数。
此外,CPU 比较整数的速度比任何其他类型都快得多。考虑在遍历元素时实现更多的整数比较。
如果您对衡量性能感兴趣,请阅读有关评估程序相对性能的 Big 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 条件。
我有几个通用列表,一个有超过 70,000 个项目,另一个有 10 个项目。与第一个列表进行比较时,我必须找出第二个列表中不存在的项目。从逻辑上讲,我的代码运行良好,并且我不会遇到较小列表集的任何严重性能问题。由于我的第一个列表超过 70K 个项目,我面临着严重的性能问题。执行和得到结果需要很多时间。
我的问题是?有没有更好的方法来做到这一点?我无法忍受这个性能问题。有什么改进建议吗?我正在使用 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>
to compare on your 4 fields then use .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
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 来存储元素。 Hash Set 要求您重载 class 的哈希函数。
此外,CPU 比较整数的速度比任何其他类型都快得多。考虑在遍历元素时实现更多的整数比较。
如果您对衡量性能感兴趣,请阅读有关评估程序相对性能的 Big 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 条件。