不确定如何制定此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中,它将是一个奖励。但是如果有必要,我知道如何在单独的查询中执行此操作。
感谢您的帮助。
答案 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));
个元素,而list2
和list1
中的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
可能会出现问题。如果已经存储在其中的对象的哈希码发生变化,一些集合类确实不会喜欢它。
此外,最佳实践也是实现HashCode
和operator==
以及IEquatable。