C# 检查每个包含另一个对象集合的对象集合是否包含列表的所有值<;字符串>;林克大道

C# 检查每个包含另一个对象集合的对象集合是否包含列表的所有值<;字符串>;林克大道,c#,linq,C#,Linq,我有一个对象集合,其中每个对象包含另一个对象集合。我需要找出最快的方法来检查它是否包含List的所有值 以下是一个例子: class Video { List<Tag> Tags; } class Tag{ public Tag (string name){ Name = name; } string Name; } List<string> selectedTags = new List<string>();

我有一个对象集合,其中每个对象包含另一个对象集合。我需要找出最快的方法来检查它是否包含
List
的所有值

以下是一个例子:

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);  
videoB
应该由LINQ选择,因为它包含所有标签

// 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);  
我尝试了
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;
IEnumerable=来自视频中的视频
视频标签在哪里(我不知道)
选择视频;

我用
.Any
.All
等尝试了几种方法。。但是我找不到解决方案,也不能使用
.Intersect
,因为一个是字符串的
列表
,另一个是对象的
列表。请注意,在生产版本中,
Video
Tag
元素具有更多属性。

对于当前代码,您在逻辑上需要:

这是假设您已经公开了
Tag.Name
Video.Tags
,当然,最好是作为属性而不是字段

请注意,我们是如何针对
selectedTags
调用
All
,因为(假设我正确阅读了您的要求)所有选定的标记都出现在视频中很重要-选择所有视频的标记并不重要

如果你有很多标签要检查,而且每个视频都有很多标签,那么这可能会比较慢

然而,知道如何优化它实际上取决于其他一些选择:

  • 如果标签的顺序不重要,您能否将
    Video.tags
    更改为集合而不是列表
  • 您是否总是浏览同一组视频,以便执行一些预处理
  • 可用标签的总数是否很大?每个视频的标签数量是多少?所选标签的数量如何
或者,您可以将每个视频投影到其“标签列表”中,并检查所选集合中是否有不在视频集合中的任何视频:

var result = videos.Where(vid => !selectedTags.Except(vid.Tags.Select(t => t.Name))
                                              .Any());

标签的顺序重要吗?或者你是把它们当作集合来处理吗?不,顺序并不重要,因为
vid.tags.
可能需要投影,因为
selectedTags
是一个
列表
,而内部集合是一个
列表
(因此当前的
包含的
将不起作用)。我不这么认为,因为在“selectedTags.All(tag”>“tag”是字符串,但此处的“vid.Tags.Contains(tag))”>“tag”是字符串“必须是标记对象,因此它不能等于字符串。如果视频有列表标签,你的解决方案就可以了。如果我是,请纠正我wrong@OselMikoD伊沃鲁贝克:啊,我没有注意到这一点。我愚蠢地期望名为
selectedTags
的变量是
列表
,而不是
列表
。你能修改你的代码使数据模型更加一致吗?@AdamHouldsworth:我已经修改了我的答案,这样它就可以与当前的设置一起工作,但我仍然认为避免一个字符串集合和一个
标记
对象集合会更干净。一致性使代码更清晰:)我认为从问题名称和描述可以明显看出,我需要将其与列表进行比较。。。
var result = videos.Where(vid => selectedTags.All(tag => 
                                      vid.Tags.Any(t => t.Name == tag)));
var result = videos.Where(vid => !selectedTags.Except(vid.Tags.Select(t => t.Name))
                                              .Any());