我有一个ID列表和一组对象,每个对象都有自己的ID子列表。我想要一个linq查询,它将返回其子列表与ID列表完全匹配的任何对象。这是我拥有的,我认为它有效 - 但它很难看,需要两个步骤。有更好的方法吗?
var inputIDs = new List<int> {1, 5, 8, 10, 12};
var object1 = new {name = "object1", IDs = new List<int> {9, 10, 11, 12}};
var object2 = new {name = "object2", IDs = new List<int> {1, 5, 8, 12}};
var object3 = new {name = "object3", IDs = new List<int> {1, 5, 8, 10, 12}};
var objects = new List<object> {object1, object2, object3};
var candidateObjects = objects.Where(o => o.IDs.All(i => inputIDs.Contains(i)));
var exactMatches = candidateObjects.Where(o => inputIDs.All(i => o.IDs.Contains(i)));
// exactMatches should only contain object3
答案 0 :(得分:5)
我认为你想要的是Enumerable.SequenceEqual
:
var inputIDs = new List<int> { 1, 5, 8, 10, 12 };
var object1 = new { name = "object1", IDs = new List<int> { 9, 10, 11, 12 } };
var object2 = new { name = "object2", IDs = new List<int> { 1, 5, 8, 12 } };
var object3 = new { name = "object3", IDs = new List<int> { 1, 5, 8, 10, 12 } };
var objects = new[] { object1, object2, object3 }.ToList();
var exactMatches = objects.Where(o => o.IDs.SequenceEqual(inputIDs));
根据@AnupSharma,你需要对你的序列是否出现故障进行排序(现在表现突然出现):
var inputIDs = new[] { 1, 5, 8, 10, 12 }.OrderBy(i => i).ToList();
//...
var exactMatches = objects.Where(o => o.IDs.OrderBy(i => i).SequenceEqual(inputIDs));
通过测试Count
可以获得(轻微)性能提升,因为我们知道来源是List
s:
var exactMatches = objects.Where(o => o.IDs.Count == inputIDs.Count && o.IDs.OrderBy(i => i).SequenceEqual(inputIDs));
答案 1 :(得分:2)
类似但更快的解决方案是使用Except
进行计数检查:
objects.Where(o => !o.IDs.Except(inputIDs).Any() && o.IDs.Count == inputIDs.Count);
答案 2 :(得分:1)
我认为添加一个元素数量的检查就足够了你的例子
var result = objects.Where(o => o.IDs.Count == inputIDs.Count)
.Where(o => o.IDs.All(id => inputIDs.Contains(id)));
您可以使用HashSet
var inputs =new HashSet<int>(inputsIDs);
var result = objects.Where(o => o.IDs.Count == inputIDs.Count)
.Where(o => o.IDs.All(id => inputs.Contains(id)));