c#Linq-检查组合键是否在另一个列表中

时间:2018-12-14 19:33:10

标签: c# linq

我有一个错误列表,定义如下:

List<Errors> test1 = new List<Errors>();

public class Errors
{
    public int ID {get; set;}
    public int Occurrence {get; set;}
    //.....
    //.....
}

通过上面两个字段的组合,错误是唯一的。

第二个列表跟踪谁被分配了错误。

List<Tasks> test2 = new List<Tasks>();

public class Tasks
{
    public int ID {get; set;}
    public int Occurrence {get; set;}
    public int EmployeeID {get; set;}
    //.....
}

通过相同的两个字段也变得唯一。本质上,tasks是已分配给某人的errors的子集。

我想使用LINQ查询(或等效查询)来确定List<Errors>中是否存在来自List<Tasks>的组合ID。要清楚,它必须同时使用两个IDS。

我找到了以下解决方案,但无法将其用于组合键。

`var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t2.Contains(t1)));`

4 个答案:

答案 0 :(得分:1)

您快到了,只需在LINQ表达式中添加一个正确的条件即可:

var test2NotInTest1 = listOfErrors.Where(e => !listOfTasks.Any(t => t.ID == e.Id && t.Occurrence == e.Occurrence)).ToList();

答案 1 :(得分:1)

只需使用和&&运算符,然后检查两个属性而不是一个:

var test2NotInTest1 = test2.Where(t2 => !test1.Any(t1 => t1.ID == t2.ID && t1.Occurance == t2.Occurance);

答案 2 :(得分:1)

有一个功能……除了

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;
    }
}

答案 3 :(得分:1)

  

对于:确定错误中的组合ID是否在任务中存在

另一种方法是使用Enumerable.Join Method

var assignedErrors = 
    errors.Join(tasks,  
                error => new { Id = error.Id, Occurrence = error.Occurrence },
                task => new { Id = task.Id, Occurrence = task.Occurrence },
                (error, task) => error);
  

针对:确定错误...中的组合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;
        }            
    }
}

用法:

var notAssignedErrors = errors.NotAssignedIn(tasks);