不确定如何制定此Linq查询。我有两个列表,每个列表都包含HashCheck对象:
class HashCheck
{
public string Id {get; set;}
public string Hash {get; set;}
}
因此,给定
List<HashCheck> list1;
List<HashCheck> list2;
我需要一个查询,它将产生一个列表,其中行的Ids匹配,但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中,那将是一个额外的奖励。但如果有必要,我知道如何在单独的查询中做到这一点。
谢谢你的帮助。
发布于 2018-05-31 05:29:02
尝试以下代码:
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>();
您可以使用join。类似于下面的代码:
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>();
发布于 2018-05-31 05:46:36
看起来您希望结果包含来自list2
的HashCheck
对象,这意味着:
var ans = list2.Where(hc2 => !list1.Any(hc1 => hc1.Id == hc2.Id && hc1.Hash == hc2.Hash));
例如,返回所有list2
元素,但不包含在Id
和Hash
中都匹配的list1
元素。
如果list1
(和/或list2
)非常大,并且考虑到性能,则可以将list1
转换为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
/GetHashCode
,然后你就可以使用LINQ 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);
注意:如果您的HashCode
对象没有被视为不可变的,那么以这种方式实现Equals
/GetHashCode
可能会有问题。如果已经存储在集合类中的对象的散列代码发生了变化,一些集合类真的不会喜欢它。此外,最佳实践是实现operator==
和operator!=
,可能还有IEquatable。
https://stackoverflow.com/questions/50613477
复制相似问题