C#Linq查询完全匹配列表

时间:2018-03-30 19:54:02

标签: c# linq

我有一个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

3 个答案:

答案 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)));