C#Linq查询精确匹配列表

C#Linq查询精确匹配列表,c#,linq,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 =

我有一个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
var-inputIDs=新列表{1,5,8,10,12};
var object1=new{name=“object1”,IDs=newlist{9,10,11,12};
var object2=new{name=“object2”,IDs=newlist{1,5,8,12};
var object3=new{name=“object3”,IDs=newlist{1,5,8,10,12};
var objects=新列表{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应仅包含object3

类似但更快的解决方案将使用
,除了带有计数检查的

objects.Where(o => !o.IDs.Except(inputIDs).Any() && o.IDs.Count == inputIDs.Count);

我认为为您的示例添加元素计数检查就足够了

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)));
var输入=新哈希集(inputsid);
var result=objects.Where(o=>o.IDs.Count==inputIDs.Count)
其中(o=>o.id.All(id=>inputs.Contains(id));

我想你想要的是可枚举的。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));
通过测试
Count
可以(轻微)提高性能,因为我们知道来源是
List
s:

var exactMatches = objects.Where(o => o.IDs.Count == inputIDs.Count && o.IDs.OrderBy(i => i).SequenceEqual(inputIDs));

你会接受linq之外的解决方案吗?你的子ID列表是否会包含重复的ID,比如
new{name=“object3”,IDs=new list{1,1,5,8,10}?您知道您可以链接这两个步骤吗?您可以显示一个示例,如给定列表和预期列表吗?
.SequenceEqual
将为包含相同顺序的完全相同元素的两个列表返回true。这就是你想要的吗?您不会显示任何具有所有
inputid但顺序不同的对象示例,也不会显示所有inputid加上其他不同数字的对象示例,也不会显示所有inputid加上一个或多个重复数字的对象示例。如果您添加这些输入,
{1,8,5,12,10},{1,5,8,8,10,12},{1,5,7,8,10,12}
那就是我要说的!谢谢如果顺序不一致,这将不起作用。我可以保证它们顺序一致。很抱歉,应该在问题中包括这一点。@AnupSharma此时的
Except
/
Count
可能同样有效。@NetMage Except/Count应该比OrderBy/SequenceEqual快一点。除了O(2n)(在这种情况下),Count是O(1),OrderBy是O(n.logn)。
var exactMatches = objects.Where(o => o.IDs.Count == inputIDs.Count && o.IDs.OrderBy(i => i).SequenceEqual(inputIDs));