我有一个对象集合,其中每个对象包含另一个对象集合。我需要找出检查它是否包含List<string>
的所有值的最快方法。
以下是一个例子:
class Video {
List<Tag> Tags;
}
class Tag{
public Tag (string name){
Name = name;
}
string Name;
}
List<string> selectedTags = new List<string>();
selectedTags.Add("Foo");
selectedTags.Add("Moo");
selectedTags.Add("Boo");
List<Video> videos = new List<Video>();
// Case A
Video videoA = new Video();
videoA.Tags = new List<Tag>();
videoA.Tags.Add(new Tag("Foo"));
videoA.Tags.Add(new Tag("Moo"));
videos.Add(videoA);
LINQ选择 videoA
,因为它不包含所有标记。
// Case B
Video videoB = new Video();
videoB.Tags = new List<Tag>();
videoB.Tags.Add(new Tag("Foo"));
videoB.Tags.Add(new Tag("Moo"));
videoB.Tags.Add(new Tag("Boo"));
videos.Add(videoB);
LINQ选择 videoB
,因为它包含所有标记。
我用foreach
循环尝试了这个,但它太慢了所以我正在寻找一个LINQ解决方案。
foreach (Video video in videos) {
if (video.Tags.Count() > 0) {
bool containAllTags = true;
foreach (string tagToFind in selectedTags) {
bool tagFound = false;
foreach (Tag tagItem in video.Tags) {
if (tagToFind == tagItem.Name)
tagFound = true;
}
if (!tagFound)
containAllTags = false;
}
if (containAllTags)
result.Add(videoItem);
}
}
生成的LINQ应如下所示:
IEnumerable<Video> = from vid in videos
where vid.Tags.( ..I dont know.. )
select vid;
我尝试了.Any
,.All
等多种方式。但是我找不到解决方案而我无法使用.Intersect
,因为一个是{{1}字符串,另一个是List
个对象。请注意,在生产版本中,List
和Video
元素具有更多属性。
答案 0 :(得分:3)
使用您当前的代码,您逻辑想要:
IEnumerable<Video> result = from vid in videos
where selectedTags.All(tag =>
vid.Tags.Any(t => t.Name == tag))
select vid;
或等效地:
var result = videos.Where(vid => selectedTags.All(tag =>
vid.Tags.Any(t => t.Name == tag)));
这假设您已将Tag.Name
和Video.Tags
公开 - 当然 - 理想情况下是属性而不是字段。
请注意我们如何针对All
致电selectedTags
,因为(假设我已正确阅读您的要求),所有选定的代码都存在于其中非常重要视频 - 选择所有视频标签非常重要
现在可能相对较慢,如果你有很多要检查的标签和每个视频的很多标签。
然而,了解如何优化它将取决于其他一些选择:
Video.Tags
更改为集合而不是列表?或者,您可以将每个视频投影到其标签列表&#34;并检查所选集中是否有任何不在视频集中的内容:
var result = videos.Where(vid => !selectedTags.Except(vid.Tags.Select(t => t.Name))
.Any());