检查每个包含另一个对象集合的对象集合是否包含List <string>通过LINQ </string>的所有值

时间:2014-03-26 15:50:26

标签: c# linq

我有一个对象集合,其中每个对象包含另一个对象集合。我需要找出检查它是否包含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个对象。请注意,在生产版本中,ListVideo元素具有更多属性。

1 个答案:

答案 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.NameVideo.Tags公开 - 当然 - 理想情况下是属性而不是字段。

请注意我们如何针对All致电selectedTags,因为(假设我已正确阅读您的要求),所有选定的代码都存在于其中非常重要视频 - 选择所有视频标签非常重要

现在可能相对较慢,如果你有很多要检查的标签和每个视频的很多标签。

然而,了解如何优化它将取决于其他一些选择:

  • 如果代码的顺序不重要,您是否可以将Video.Tags更改为集合而不是列表?
  • 您是否一直在查看同一组视频,以便进行一些预处理?
  • 可用的标签总数是多少?每个视频的标签数量怎么样?所选标签的数量如何?

或者,您可以将每个视频投影到其标签列表&#34;并检查所选集中是否有任何不在视频集中的内容:

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