Linq查询从行不同的两个列表中筛选

时间:2018-05-30 21:18:26

标签: linq

不确定如何制定此Linq查询。 我有两个列表,每个列表都包含HashCheck对象:

class HashCheck
{
   public string Id {get; set;}
   public string Hash {get; set;}
}

所以,给定

List<HashCheck> list1;
List<HashCheck> list2;

我需要一个查询,该查询将导致列表中包含行的ID匹配的行,但Hash不会。

所以例如

List1 =   
{1, 12345,  
 2, 34323,  
 3, 34083,  
 4, 09887}  

List2 =  
{1, 00001,  << matching id, not matching hash  
 2, 34323,  
 3, 11112,  << matching id, not matching hash  
 4, 09887  
 5, 98845}  

ResultList =  
{1, 00001,  
 3, 11112}  

注意:在List2中,有一个额外的行,如果它包含在ResultList中,它将是一个奖励。但是如果有必要,我知道如何在单独的查询中执行此操作。

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

试试这段代码:

     var list3 = (from i in list1
                  from j in list2
                  where i.Id == j.Id && i.Hash != j.Hash
                  select new HashCheck() { Id = j.Id, Hash = j.Hash
                  }).ToList<HashCheck>();

您可以使用加入。类似下面的代码:

      var list3 = (from i in list1
                   join j in list2 on i.Id equals j.Id
                   where i.Hash != j.Hash
                   select new HashCheck() { Id = j.Id, Hash = j.Hash 
                   }).ToList<HashCheck>();

答案 1 :(得分:1)

您希望结果包含来自HashCheck的{​​{1}}个对象,这只是意味着:

list2

e.g。返回所有var ans = list2.Where(hc2 => !list1.Any(hc1 => hc1.Id == hc2.Id && hc1.Hash == hc2.Hash)); 个元素,而list2list1中的Id元素不匹配。

如果Hash(和/或list1)非常大并且考虑了性能,您可以将list2转换为list1并对其进行查找:< / p>

Dictionary

另一种方法是为您的班级实施var list1map = list1.ToDictionary(hc1 => hc1.Id, hc1 => hc1.Hash); var ans2 = list2.Where(hc2 => !list1map.TryGetValue(hc2.Id, out var hash1) || hash1 != hc2.Hash); / Equals,然后您可以使用LINQ GetHashCode

将以下方法添加到您的课程中:

Except

现在计算很简单:

public override bool Equals(object other) => (other is HashCheck hco) ? Id == hco.Id && Hash == hco.Hash : false;
public override int GetHashCode() => (Id, Hash).GetHashCode();

注意:如果您的var ans3 = list2.Except(list1); 对象不被视为不可变,则以这种方式实施Equals / GetHashCode可能会出现问题。如果已经存储在其中的对象的哈希码发生变化,一些集合类确实不会喜欢它。 此外,最佳实践也是实现HashCodeoperator==以及IEquatable。