c#Linq-检查另一个列表中是否存在复合密钥
我有一个错误列表,定义如下:c#Linq-检查另一个列表中是否存在复合密钥,c#,linq,C#,Linq,我有一个错误列表,定义如下: List<Errors> test1 = new List<Errors>(); public class Errors { public int ID {get; set;} public int Occurrence {get; set;} //..... //..... } 您就快到了,只需在LINQ表达式中添加一个正确的条件: var test2NotInTest1 = listOfErrors.W
List<Errors> test1 = new List<Errors>();
public class Errors
{
public int ID {get; set;}
public int Occurrence {get; set;}
//.....
//.....
}
您就快到了,只需在LINQ表达式中添加一个正确的条件:
var test2NotInTest1 = listOfErrors.Where(e => !listOfTasks.Any(t => t.ID == e.Id && t.Occurrence == e.Occurrence)).ToList();
您就快到了,只需在LINQ表达式中添加一个正确的条件:
var test2NotInTest1 = listOfErrors.Where(e => !listOfTasks.Any(t => t.ID == e.Id && t.Occurrence == e.Occurrence)).ToList();
只需使用and
&&
运算符并检查两个属性,而不是一个:
var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t1.ID == t2.ID && t1.Occurance == t2.Occurance);
只需使用and
&&
运算符并检查两个属性,而不是一个:
var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t1.ID == t2.ID && t1.Occurance == t2.Occurance);
有一个函数用于。。。除了
var test2NotInTest1 = test1.Except(test2);
如果没有,则需要为equal创建接口,如下所示:
var test2NotInTest1 = test1.Except(test2, new ErrorsComparer());
class ErrorsComparer : IEqualityComparer<Errors>
{
public bool Equals(Errors x, Errors y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the products' properties are equal.
return x.ID == y.ID && x.Occurrence == y.Occurrence;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Errors e)
{
if (Object.ReferenceEquals(e, null)) return 0;
int hashID = e.ID == null ? 0 : e.ID.GetHashCode();
int hashO = e.Occurrence.GetHashCode();
//Calculate the hash code for the product.
return hashID ^ hashO;
}
}
var test2NotInTest1=test1.Except(test2,newerrorscomparer());
类错误比较者:IEqualityComparer
{
公共布尔等于(错误x,错误y)
{
//检查比较对象是否引用相同的数据。
if(Object.ReferenceEquals(x,y))返回true;
//检查是否有任何比较对象为空。
if(Object.ReferenceEquals(x,null)| | Object.ReferenceEquals(y,null))
返回false;
//检查产品的属性是否相等。
返回x.ID==y.ID&&x.Occurrence==y.Occurrence;
}
//对于一对对象,If Equals()返回true
//然后GetHashCode()必须为这些对象返回相同的值。
public int GetHashCode(错误e)
{
if(Object.ReferenceEquals(e,null))返回0;
int hashID=e.ID==null?0:e.ID.GetHashCode();
int hashO=e.Occurrence.GetHashCode();
//计算产品的哈希代码。
返回hashID^hashO;
}
}
有一个函数用于。。。除了
var test2NotInTest1 = test1.Except(test2);
如果没有,则需要为equal创建接口,如下所示:
var test2NotInTest1 = test1.Except(test2, new ErrorsComparer());
class ErrorsComparer : IEqualityComparer<Errors>
{
public bool Equals(Errors x, Errors y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the products' properties are equal.
return x.ID == y.ID && x.Occurrence == y.Occurrence;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Errors e)
{
if (Object.ReferenceEquals(e, null)) return 0;
int hashID = e.ID == null ? 0 : e.ID.GetHashCode();
int hashO = e.Occurrence.GetHashCode();
//Calculate the hash code for the product.
return hashID ^ hashO;
}
}
var test2NotInTest1=test1.Except(test2,newerrorscomparer());
类错误比较者:IEqualityComparer
{
公共布尔等于(错误x,错误y)
{
//检查比较对象是否引用相同的数据。
if(Object.ReferenceEquals(x,y))返回true;
//检查是否有任何比较对象为空。
if(Object.ReferenceEquals(x,null)| | Object.ReferenceEquals(y,null))
返回false;
//检查产品的属性是否相等。
返回x.ID==y.ID&&x.Occurrence==y.Occurrence;
}
//对于一对对象,If Equals()返回true
//然后GetHashCode()必须为这些对象返回相同的值。
public int GetHashCode(错误e)
{
if(Object.ReferenceEquals(e,null))返回0;
int hashID=e.ID==null?0:e.ID.GetHashCode();
int hashO=e.Occurrence.GetHashCode();
//计算产品的哈希代码。
返回hashID^hashO;
}
}
For:要确定任务中是否存在来自错误的复合ID,
另一种方法是使用
For:确定来自错误的复合ID是否在任务中不存在,如示例中所示:var test2NotInTest1=test2.Where(t2=>!test1.Any(t1=>t2.Contains(t1))代码>
您可以使用HashSet“加速”搜索已分配的错误
var assignedErrors = tasks.Select(task => (task.Id, task.Occurrence)).ToHashSet();
var notAssignedErrors =
errors.Where(error => assignedErrors.Contains((error.Id, error.Occurrence)) == false)
.ToList();
或者创建自己的特定于域的扩展方法:
public static IEnumerable<Errors> NotAssignedIn(
this IEnumerable<Errors> errors,
IEnumerable<Tasks> tasks)
{
var assigned = new HashSet<(int Id, int Occurrence)>();
foreach (var task in tasks)
{
assigned.Add((task.Id, task.Occurrence));
}
foreach (var error in errors)
{
if (assigned.Contains((error.Id, error.Occurrence)) == false)
{
yield return error;
}
}
}
For:要确定任务中是否存在来自错误的复合ID,
另一种方法是使用
For:确定来自错误的复合ID是否在任务中不存在,如示例中所示:
var test2NotInTest1=test2.Where(t2=>!test1.Any(t1=>t2.Contains(t1))代码>
您可以使用HashSet“加速”搜索已分配的错误
var assignedErrors = tasks.Select(task => (task.Id, task.Occurrence)).ToHashSet();
var notAssignedErrors =
errors.Where(error => assignedErrors.Contains((error.Id, error.Occurrence)) == false)
.ToList();
或者创建自己的特定于域的扩展方法:
public static IEnumerable<Errors> NotAssignedIn(
this IEnumerable<Errors> errors,
IEnumerable<Tasks> tasks)
{
var assigned = new HashSet<(int Id, int Occurrence)>();
foreach (var task in tasks)
{
assigned.Add((task.Id, task.Occurrence));
}
foreach (var error in errors)
{
if (assigned.Contains((error.Id, error.Occurrence)) == false)
{
yield return error;
}
}
}
它将比较哈希代码,而不是字段OPneeds@Fabjan你不认为有错误的理由吗?我不知道是什么让你认为有错误。。。好吧,这只是OP拥有的一个自定义类created@LCaraway它应该更快——它只需要为list1和list2计算一次散列,因此它应该在O(n1+n2)处运行——使用与嵌套循环相同的任何函数,将得到O(n1*n2)(其中nX是两个列表的len。)非常容易测试。上次我不得不这么做时,我看到了速度的提高。注意,如果您的列表很小(<100)请使用where方法),我担心这不会针对OP case编译,因为OP需要比较不同类型的列表错误和任务。它将比较hashcode,而不是OP字段needs@Fabjan你不认为有错误的理由吗,我不知道是什么让你认为有。。。好吧,这只是OP拥有的一个自定义类created@LCaraway它应该更快——它只需要为list1和list2计算一次散列,因此它应该在O(n1+n2)处运行——使用与嵌套循环相同的任何函数,将得到O(n1*n2)(其中nX是两个列表的len。)非常容易测试。上次我不得不这么做时,我看到了速度的提高。注意,如果您的列表很小(<100),请使用where方法),恐怕这不会针对OP案例进行编译,因为OP需要比较不同类型的Errors
和Tasks
的列表。仅供参考,通常类的名称是单数的(即Task
和Error
),除非它们是集合类型。然后这些类型的集合将具有复数名称(就像您在代码中所做的那样)。仅供参考,通常类具有单数名称(即Task
和Error
),除非它们是集合类型。然后这些类型的集合将具有复数名称(就像您在代码中所做的那样)。这不执行内部联接吗。我想他想要的是一个左侧连接,右侧为null的Except。@Hogan,为了确定列表中的复合ID是否存在于列表中,如果我正确理解OP,那么“存在于”应该是“join”——哇,我完全没有读到这个问题——我想他想要的是一个Except。很抱歉